#class 定义一个类,类名一般首字母大写
#def 定义一个函数,自带self形参
# 类中包含两种内容:1、静态属性(变量); 2、动态属性(方法、函数)
class Test:
s1 = 'test'
def __init__(self, a):
self.aa = a
print('init', self, self.aa) # init <__main__.Test object at 0x7f920ea10f70> aaa 创建对象时会自动执行
def T1(self, b):
return b
#类名的用途:1、访问静态和动态属性;2、创建一个对象;
print(Test.s1) # test 直接访问静态属性
print(Test.T1(1, 2))# 2 直接访问动态属性,因为init会默认执行,所以需要给init传值
print(Test.__dict__)# 类的内容以字典形式存储,内置函数dict可查看
"""
{'__module__': '__main__', 's1': 'test', '__init__': <function Test.__init__ at 0x7f805fa06dc0>, 'T1': <function Test.T1 at 0x7f805fa06f70>, '__dict__': <attribute '__dict__' of 'Test' objects>, '__weakref__': <attribute '__weakref__' of 'Test' objects>, '__doc__': None}
"""
obj = Test('aaa')# 创建对象,格式: 对象 = 类名(init所需参数)
print(obj) # <__main__.Test object at 0x7fdb6498ffa0>
print(obj.aa) # aaa
re = obj.T1('b')
print(re)# b
from math import pi
# 对象嵌套
class Circular():
def __init__(self, r);
self.r = r
def C(self):
return 2 * pi * self.r
def S(self):
return pi * self.r ** 2
class Ring():
def __init__(self, in_r, out_r):
self.in_r = Circular(in_r)
self.out_r = Circular(out_r)
def C(self):
return self.out_r.C() - self.in_r.C()
def S(self):
return self.out_r.S() - self.in_r.S()
a = Ring(5, 10)
print(a.C())
#三大特性:继承、封装、多态
#继承:
# 1、解决代码的重复性
#单继承
class C1(): # 父类、基类、超类
def __init__(self, c1):
self.c1 = c1
class C2(C1): # 子类、派生类 括号里只能传类名
def __init__(self, c2):
self.c2 = c2
super().__init__(5) # 当父、子类均有init(或重名)时,使用父类init需要 super() 加载父类对象
print(C2.__bases__) # (<class '__main__.C1'>,) 查看父类
print(C1.__bases__) # (<class 'object'>,) 没有父类就是object,object是所有类的父类
test = C2(3)
print(test.c2) # 3
print(test.c1) # 5
#多继承
class B1():
def __init__(self, b1):
self.b1 = b1
class B2():
def __init__(self, b2):
self.b2 = b2
class B3(B1, B2):
def __init(self, b3):
self.b3 = b3
B1.__init__(self, 8)
B2.__init__(self, 9) # 多继承需要指定父类,且传参要写self
test = B3(7)
print(test.b3) # 7
print(test.b2) # 9
#抽象类: 规范所有继承这个类的子类必须实现 @abstractmethod 装饰的方法
# 在类的位置指定 metaclass=ABCMeta
# 在指定的方法上加 @abstractmethod 装饰器
# 接口类(Java知识点): 多继承抽象类,两种类都不能被实例化
from abc import abstractmethod, ABCMeta
class P1(metaclass=ABCMeta):
@abstractmethod
def p1(self, str): # 父类约束
pass
class log1(P1):
def p1(self, str): # 子类继承父类受父类约束,必须实现p1方法
print(str)
return str
class log2(P1):
def l2(self, str):
pass
def p1(self, str): # 必须实现p1方法,否则抛异常
print(str)
def Pr(obj, str):pbj.p1(str)
L1 = log1()
Pr(L1, 'hahaha')
L2 = log2()
Pr(L2, 'L2')
#钻石继承
class A:
def func(self):
print('A')
class B(A):
# B和C类都继承A,当B没有func()对象时,遵循广度优先算法;如果B和C继承不同类,遵循深度优先
# def func(self):
# print('B')
pass
class C(A):
def func(self):
print('c')
class D(B, C):pass
d = D()
d.func() # c
# 类名.mro() 可以直接将继承顺序输出,super()父类继承也遵循该顺序
print(D.mro())# [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
#多态,Java类需指定参数的类型,将多种类型定义到一个类中,后续类继承定义了多种数据类型的类,即为多态;
#python不需要指定参数类型,默认多态
#封装
class E():
def __init__(self):
self.__test = 'T' # 双下划线定义为 私有变量; 注意类的外部不可以定义私有变量
print('11111', test) # 直接输出会输出对象 11111 <__main__.B3 object at 0x7f85ab209e80>
self.test1 = 'T1'
self.__test2()
def __test2(self): # 私有方法
print('Test2')
def test3(self):
print(self.__test)
class F(E):
def __init__(self):
self.__test2()
e = E()
# print(e.__test)# 异常,私有变量在类外部不可用
print(e.__dict__) # 返回字典中有 _E__test 一个变量,其实是私有变量的名字 {'_E__test': 'T', 'test1': 'T1'}
print(e._E__test) # T 可以强制访问到,但不推荐
print(e.test1) # T1
#e.__test2()# 异常,私有类不能在外部使用
e.test3() # T
# f = F()# 异常,私有类不能继承,所以子类也不可用