python 面向对象 【进阶】
多态
多态跟python没有太大关系,因为python本身原生支持多态。
class A: pass class B(A): pass class C(A): pass def func(A arg): #可以是B类,也可以是C类 print(arg) obj=B() obj1=C()
这个例子说明的是,如果A是int类型的,传参可以传int类型和int的派生类型。
直白的说,就是传参可以传所有的A类型,或者所有的A的子类类型,利用类的继承关系。
ps:python原生支持多态的缺点就是看源码不是特别方便,因为你不知道传的是什么类型的参数。
面向对象之类的成员
类的成员可以分为三部分:字段、方法和属性。
ps:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就是有多少个普通字段。而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份。
字段
字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同。
- 普通字段属于对象
- 静态字段属于类
class Province: # 静态字段 country = '中国' def __init__(self, name): # 普通字段 self.name = name # 直接访问普通字段 obj = Province('河北省') print obj.name # 直接访问静态字段 Province.country
一般情况:自己访问自己字段
规则:普通字段只能用对象访问
静态字段只能用类访问(万不得已的时候可以使用对象访问)
特殊情况:静态字段也可以用对象访问
由上述代码可以看出【普通字段需要通过对象来访问】【静态字段通过类访问】,在使用上可以看出普通字段和静态字段的归属是不同的。其在内容的存储方式类似如下图:
由上图可是:
- 静态字段在内存中只保存一份
- 普通字段在每个对象中都要保存一份
应用场景: 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段
ps:静态字段在代码加载时,已经创建
方法
方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。
- 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
- 类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
- 静态方法:由类调用;无默认参数;
class Foo: def __init__(self,name): self.name = name self.country = "China" def show(self): '''普通方法,至少一个self参数''' print(self.name) @staticmethod def f1(arg): '''静态方法,任意参数''' print(arg) @classmethod def f2(cls): #class的缩写 '''类方法,至少一个cls参数''' print(cls) obj = Foo('pando') obj.show() #调用普通方法 Foo.f1(222) #调用静态方法 Foo.f2() #调用类方法
执行结果:
pando 222 <class '__main__.Foo'>
方法
所有方法都属于类
1.普通方法:至少一个self参数,对象执行
2.静态方法:任意参数,类执行(万不得已可以用对象执行)
3.类方法:至少一个cls参数,类执行(万不得已可以用对象执行)
类方法:其实是静态方法的一种特殊形式,唯一的特殊功能就是 自动把类名当作参数传递。
属性
属性:具有方法的表现形式,具有字段的访问形式,python中的属性其实是普通方法的变种。
属性的基本使用方法
class Mo: def func(self): pass # 定义属性 @property def prop(self): pass mo_obj = Mo() mo_obj.func() #调用方法 mo_obj.prop #调用属性
属性的定义和调用要注意以下几点:
定义时,在普通方法的基础上添加 @property 装饰器;
定义时,属性仅有一个self参数
调用时,无需括号
方法:foo_obj.func()
属性:foo_obj.prop
获取、修改、删除属性
class Goods(object): @property def price(self): print ('@property') @price.setter def price(self, value): print ('@price.setter,',value) @price.deleter def price(self): print ('@price.deleter') # ############### 调用 ############### obj = Goods() obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值 obj.price = 123 # 自动执行 @price.setter 修饰的 price 方法,并将 123 赋值给方法的参数 del obj.price # 自动执行 @price.deleter 修饰的 price 方法
执行结果:
@property @price.setter, 123 @price.deleter
属性的三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
另一种常用表现形式
class Goods(object): def get_price(self): print ('@property') def set_price(self, value): print ('@price.setter,',value) def del_price(self): print ('@price.deleter') foo =property(fget=get_price,fset=set_price,fdel=del_price) # ############### 调用 ############### obj = Goods() obj.foo # 自动执行 @property 修饰的 price 方法,并获取方法的返回值 obj.foo = 123 # 自动执行 @price.setter 修饰的 price 方法,并将 123 赋值给方法的参数 del obj.foo # 自动执行 @price.deleter 修饰的 price 方法
执行结果:
@property @price.setter, 123 @price.deleter
【面向对象之成员修饰符】