(一)面向对象编程
在面向对象中最紧张的三个部分分别是:封装、继承、多态
可参考我前面的条记:https://www.jianshu.com/p/92790574f3d2
在学习这些之前,我们先明白两个概念:类、对象
- 类(class):形貌具有类似属性和方法的对象的聚集。比方:人类。
- 对象(object):通过对类举行实例化,分配内存空间,能可以或许被用户利用。比方:张三。
# 类class Person(): name="人类有个名字" age="人类有年岁" sex="人类有性别"# 对象p1 = Person()p1.name = "我叫张三"p1.age = 18p1.sex = "man"print(type(p1)) # <class '__main__.Person'>(1)封装(encapsulation)
将一个类的全下属性和方法放到一起,大概说将数据和功能汇聚到一起。
封装可以或许包管类内部数据布局的完备性,只答应用户利用公开的数据,不答应利用私有数据,克制了外部对内部数据的影响,从而进步了步伐的可维护性。
起首我们来看看,对象生命周期和函数实验的序次:
self:代表当前对象,可以在类的内部直接访问任何类的变量和方法,类内里的全部函数都以self作为第一个参数。(self不是关键字,只是形参的名字)
class Person(): """人类""" # 这个方法一般不利用 def __new__(cls,*args, **kwargs): print("new") return super().__new__(cls) # 一个人诞生了,须要给它起个名字,初始化年岁等 def __init__(self,name,age) -> None: print("初始化函数") # 实例化对象的时间会主动调用 self.name = name self.age = age self.print_name() def print_name(self): print("我是:",self.name) def __del__(self): print("析构函数")# 开释对象的时间会主动调用p1 = Person("张三", 18)# new# 初始化函数# 我是: 张三# 析构函数类变量和实例变量
- 类变量:类变量是每一个类都有的变量,新创建的每一个实例的类变量都是一样的,所在也都一样。类变量可以是可变变量和不可变变量。我们可以以通过实例和类访问到类变量,如果类变量是可变变量,只要在一个实例中改变类变量,其他实例访问的时间也会改变。不保举利用实例访问类变量。
- 实例变量:是每一个实例私有的,每个实例的变量的所在都差异,每个实例之间不会相互影响。而且无法通过类名访问。
私有变量:私有成员变量,外部不能访问。以__开头
私有方法:私有成员方法,外部不能访问。以__开头
理论上私有变量是不答应外部访问的,但是python给我们开了个后门,我们可以利用实例名._类名__变量名来访问
class Person(): # 类变量 sex = "man" list1 = [1,2,3] __a = 1 # 私有成员变量 # 初始化函数 def __init__(self, name) -> None: self.name = name # 私有成员方法 def __get_a(self): __a = 3 # 内部可以访问,外部不能访问# 两个都叫张三的人p1 = Person("张三")p2 = Person("张三")# 类变量, 不可变变量print(Person.sex == p1.sex == p2.sex, id(Person.sex), id(p1.sex), id(p2.sex)) # True 1371018000456 1371018000456 1371018000456p1.sex = "woman"print(Person.sex == p1.sex == p2.sex, id(Person.sex), id(p1.sex), id(p2.sex)) # False 1371018000456 1371047207352 1371018000456# 类变量, 可变变量print(Person.list1 == p1.list1 == p2.list1, id(Person.list1), id(p1.list1), id(p2.list1)) # True 1371046436744 1371046436744 1371046436744Person.list1.append(4)print(Person.list1 == p1.list1 == p2.list1, id(Person.list1), id(p1.list1), id(p2.list1)) # True 1371046436744 1371046436744 1371046436744# 实例变量print(id(p1.name), id(p2.name)) # 1371047341288 1371047984448print(Person.name) # AttributeError: type object 'Person' has no attribute 'name'# 私有成员变量&方法print(p1.__a) # AttributeError: 'Person' object has no attribute '__a'print(p1.__get_a()) # AttributeError: 'Person' object has no attribute '__get_a'print(p1._Person__a) # 1类方法属于类但不属于实例的方法,须要在方法前面利用@classmethod标记。
静态方法借居在类中,独立存在,不能调用对象方法和类方法(类名.方法名除外),须要在方法前面利用@staticmethod标记。
property 装饰器让一个方法被当成属性来调用,不能传入参数,,须要在方法前面利用@property标记
python另有许多的魔术方法:
class A(): def __init__(self) -> None: pass @classmethod def a(self): print("类方法") @staticmethod def b(): # 无需传入self print("静态方法") @property def c(self): print("c") def __str__(self) -> str: return "hello, this is the object of A" def d(self): print("d")a1 = A()A.a() # 类方法A.b() # 静态方法A.c # cA.d(self=1)# 可以利用类名调用实例方法但是须要手动传入self参数a1.a() # 类方法a1.b() # 静态方法a1.c # ca1.c() # c TypeError: 'NoneType' object is not callableprint(a1) # hello, this is the object of A(2)继承
子类通过继承父类从而获取父类的属性和方法。
如果父类和子类有类似名称的方法大概属性,会被后者覆盖。可以通过super调用父类的重名函数。
一个类也可以继承于多个父类。
class Person(): # 父类 title="人类" __a = "a" def print_title(self): print(Person.title)class Teacher(Person): # 子类 name = "老师"class Student(Person): # 子类 name = "门生" def print_title(self): print(Student.name) def private_a(self): print(Person._Person__a) # 不保举利用t1 = Teacher()s1 = Student()t1.print_title() # 人类 继承父类方法s1.print_title() # 门生 覆盖父类方法super(Student, s1).print_title() # 人类# 访问父类私有属性s1.private_a()s1._Person__a # 'a' 不保举利用(3)多态
多态就是子类重写父类的方法,上面已经说过了。也就是子类和父类方法重名,子类方法覆盖父类方法。
class A(): def test(self): print("a")class B(A): def test(self): print("b")b = B()b.test() # b |