面向对象进阶
成员
类,对象=》静态字段,静态方法,普通字段,普通方法
通过类访问有:静态字段,静态方法
通过对象访问:普通字段,普通方法
成员修饰符
面向对象中一些常用特殊方法 __init__ __call__ __delitem__
反射查找类的成员
1 #-*- coding:utf-8 -*- 2 class abc(object): 3 def __init__(self,name): 4 self.name=name 5 def a1(self): 6 pass 7 8 9 10 f1=abc.__dict__ 11 #查看类中方法 12 #print(f1) 13 14 #反射:找类中的方法,__init__和a1 15 print(hasattr(abc,'a1')) 16 17 #反射:对象,既可以找对象还可以找类中的方法 18 f1=abc('zhangs') 19 print(hasattr(f1,'name')) 20 print(hasattr(f1,'a1'))
反射:
反射导入模块,在找类然后初始化对象,最后根据对象知道对应的方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #-*- coding:utf-8 -*- 2 3 #导入模块 4 f1=__import__('f2',fromlist=True) 5 6 #获取f1的类 7 class_name=getattr(f1,'F1') 8 9 #创建对象 10 obj=class_name("zhangs") 11 12 #获取对象中的方法 13 result=getattr(obj,'name') 14 print(result) 15 16 17 结果: 18 zhangs
类静态字段
1 #-*- coding:utf-8 -*- 2 3 class F1(object):
#类静态字段 4 country = '中国' 5 def __init__(self,name): 6 #对象方法 7 self.name=name 8 #self.country="中国" 这样写的缺点就是浪费内存,每一个对象都会有这个这个属性 9 def fun(self): 10 pass 11 12 a1=F1("黑龙江") 13 a2=F1("湖北") 14 a3=F1("湖南")
其实带self定义的就是对象方法,每生成一个对象都会有这个方法
类静态方法staticmethod
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class F1(object): 2 3 def __init__(self): 4 pass 5 #静态方法必须加这个装饰器 6 @staticmethod 7 def static_func(x): 8 print(x) 9 10 a1=F1() 11 #通过对象访问类的静态方法,原则上尽量不使用。要想使用也是用类的方法去访问 12 a1.static_func(1) 13 #通过类访问静态方法 14 F1.static_func(12)
静态方法和函数差不多,直接调用。不愿意写函数的就是用这个方法。这个方法在c#或java 中就可以实现函数的方式
类方法classmethod
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #-*- coding:utf-8 -*- 2 3 class F1(object): 4 5 def __init__(self): 6 pass 7 #静态方法必须加这个装饰器 8 @staticmethod 9 def static_func(x): 10 print(x) 11 12 #类方法会自动加一个类名,必须定义cls 13 @classmethod 14 def classfunc(cls): 15 print(cls) 16 17 F1.classfunc() 18 19 结果: 20 <class '__main__.F1'>
类方法比静态方法多一个功能就是传递一个类名
特性property
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #-*- coding:utf-8 -*- 2 3 class F1(object): 4 #普通方法 5 def s1(self): 6 print("s1") 7 8 @property 9 def s2(self): 10 print("s2") 11 12 obj1=F1() 13 #执行普通方法 14 obj1.s1() 15 #执行特性方法,特性方法不需要写(),但是也无法加参数 16 obj1.s2
将方法伪造成字段
给property赋值方法,property中还是很少用到的知道就好了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #-*- coding:utf-8 -*- 2 3 class F1(object): 4 @property 5 def s2(self): 6 print("s2") 7 #给特性方法赋值就必须这么写,下面的方法名必须和上面一样 8 @s2.setter 9 def s2(self,value): 10 print(value) 11 obj1=F1() 12 #执行特性方法 13 obj1.s2 14 #给特性方法赋值 15 obj1.s2=123 16 17 18 结果: 19 s2 20 123
成员修饰符(公开或私有)
1 class F1(object): 2 abc=123 3 __aaa=4565 4 def __init__(self): 5 self.__name="zhangs" 6 #类的内部可以正常访问私有修饰符成员 7 def s2(self): 8 print(F1.__aaa) 9 print(self.__name) 10 11 12 obj1=F1() 13 #静态方法或普通方法都不能直接访问私有修饰符成员 14 #obj1.__aaa 15 #obj1.__name 私有修饰符的普通方法也无法访问 16 17 18 #可以访问类公共修饰符变量 19 print(obj1.abc) 20 21 #内部可以正常访问私有修饰符方法 22 print(obj1.s2())
私有对象修饰符和派生类测试
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #-*- coding:utf-8 -*- 2 3 class F1(object): 4 abc=123 5 __aaa=4565 6 def __init__(self): 7 self.__name="zhangs" 8 def __test(self): 9 print("test") 10 def demo(self): 11 #内部可以调用私有修饰符成员对象 12 print self.__test() 13 14 class F2(F1): 15 def abc(self): 16 print(self.__name) 17 18 f2=F2() 19 #私有修饰符对象方法也不能直接调用,派生类也无法调用 20 # f2.abc() 21 # f2.__test() 22 f2.demo()
访问私有方法,知道就可以基本没人这么用
class f:
__name=12
f1=f()
f1_f__name
__call__方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class f1: 2 def __init__(self): 3 print("__init__") 4 5 def __call__(self, *args, **kwargs): 6 print("__call__") 7 return 1 8 9 #很特殊的call方法调用 10 f=f1()() 11 12 #上面的方法就是下面方法的简写,在看源码的时候要注意就这样写的 13 #实际上是调用的call方法 14 #f=f1() 15 #f() 16 17 print(f) 18 19 结果: 20 __init__ 21 __call__ 22 1
类成员魔法参数 __getitem__ __setitem__ __delitem__
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #-*- coding:utf-8 -*- 2 class f1: 3 def __init__(self): 4 self.dick={} 5 def __getitem__(self, item): 6 if type(item) == dict: 7 if self.dick.has_key(item):print(self.dick[item]) 8 else:print("{}") 9 else: 10 print(item) 11 12 def __setitem__(self, key, value): 13 self.dick[key]=value 14 print(key,value) 15 16 def __delitem__(self, key): 17 del self.dick[key] 18 print(key) 19 20 def __delslice__(self, i, j): 21 print("__delslice__") 22 23 def __setslice__(self, i, j, sequence): 24 print("__setslice__") 25 26 27 28 f=f1() 29 #查找 30 f['aa'] 31 32 #设置 33 f['key']="value" 34 35 #删除 36 del f['key'] 37 38 #切片 39 f[1:2] 40 41 #设置切片 42 f[1:2]=[3,6] 43 44 #删除切片 45 del f[1:2] 46 47 48 结果: 49 aa 50 ('key', 'value') 51 key 52 slice(1, 2, None) 53 __setslice__ 54 __delslice__
__iter__为什么for可以循环某些对象?
1 #-*- coding:utf-8 -*- 2 class f1: 3 #对象中包含这个方法就是说明这个对象可以被迭代了 4 def __iter__(self): 5 yield 1 6 yield 2 7 yield 3 8 9 10 11 f=f1() 12 #循环可迭代的对象 13 for i in f: 14 print(i)