python面向对象编制程序,
Python-面向对象进阶,python-进阶
一、isinstance(obj, cls) and issubclass(sub, super)
一. isinstance(obj, cls),检查obj是不是是类cls的对象
1 class A:
2 pass
3
4 obj = A()
5 print(isinstance(obj, A))
6
7 #运行结果
8 #True
贰. issubclass(sub, super),检查sub类是还是不是是super类的派生类(子类)
1 class A:
2 pass
3
4 class B(A):
5 pass
6
7 print(issubclass(B, A))
8
9 #运行结果
10 #True
二、反射
一. 什么样是反射
反射的定义是由Smith在1九8伍年第1回提出的,首要是指程序能够访问、检验和修改它自个儿意况或作为的一种力量(自省)。这一定义的提出高效引发了Computer科学领域有关使用反射性的钻研。它首先被程序语言的规划领域所运用,并在Lisp和面向对象方面获取了成绩。
二.
python面向对象中的反射:透过字符串的款式操作对象相关的属性。python中的一切事物都以目的(都能够运用反射)。
1 class People:
2 country = 'China'
3 def __init__(self, name, age):
4 self.name = name
5 self.age = age
6
7 def info(self):
8 print('%s is %d years old' % (self.name, self.age))
9
10 p = People('jack', 18)
11
12 #hasattr(obj, name),检查属性
13 print(hasattr(p, 'info')) #检查对象p是否有‘info’属性,结果True
14 print(hasattr(p, 'name')) #检查对象p是否有‘name’属性,结果True
15
16 #getattr(obj, name)获取属性
17 print(getattr(p, 'name')) #获得对象p的‘name’属性,结果:返回p.name的值,即jack
18 print(getattr(p, 'info')) #获得对象p的‘info’属性,结果:返回p.info的值,
19 # 即绑定方法info的内存地址:<bound method People.info of <__main__.People object at 0x000001B64317ABE0>>
20 getattr(p, 'info')() #由于getattr返回的是对象方法属性的内存地址,加()就可以调用,结果:jack is 18 years old
21
22 #setattr(x, y, v)设置属性
23 setattr(p, 'age', 21) #修改对象p的‘age’属性,结果:p.age的值变为21
24 setattr(p, 'sex', 'male') #新增对象p的‘sex’属性,结果:p.sex的值为male
25 print(p.__dict__) #查看对象p的数据属性,结果:{'name': 'jack', 'age': 21, 'sex': 'male'}
26
27 #delattr(x, y)删除属性
28 delattr(p, 'sex') #删除对象p的‘sex’属性
29 print(p.__dict__) #结果:{'name': 'jack', 'age': 21}
多少个可以兑现自省的函数:hasattr(obj,
name);getattr(obj, name);setattr(x, y, v);delattr(x, y)
1 #类也是对象
2 class Foo(object):
3 staticField = "old boy"
4
5 def __init__(self):
6 self.name = 'wupeiqi'
7
8 def func(self):
9 return 'func'
10
11 @staticmethod
12 def bar():
13 return 'bar'
14
15
16 print(getattr(Foo, 'staticField')) #获取类的'staticField'属性,结果:old boy
17
18 print(getattr(Foo, 'func')) #获取类的'func'属性,结果:<function Foo.func at 0x0000018156FBB950>
19 print(getattr(Foo, 'func')('self')) #加()调用方法,结果:func
20
21 print(getattr(Foo, 'bar')) #获取类的'bar'属性,结果:<function Foo.bar at 0x00000192D2AFB9D8>
22 print(getattr(Foo, 'bar')()) #加()调用方法,结果:bar
类也是目标,能够运用反射
1 #反射当前模块成员
2 #!/usr/bin/env python
3 # -*- coding:utf-8 -*-
4
5 import sys
6
7
8 def s1():
9 print('s1')
10
11
12 def s2():
13 print('s2')
14
15
16 this_module = sys.modules[__name__]
17
18 print(this_module) #结果:<module '__main__' from '......'>
19 print(hasattr(this_module, 's1')) #结果:True
20 print(getattr(this_module, 's2')) #结果:<function s2 at 0x0000020590EAB8C8>
21 getattr(this_module, 's2')() #结果:s2
模块也是目的,能够利用反射
叁. 反光的好处
便宜一:落成可插拔机制
有俩程序猿,贰个lili,三个是egon,lili在写程序的时候须求用到egon所写的类,然而egon去跟女朋友度蜜月去了,还尚未旗开得胜他写的类,lili想到了反光,使用了反光机制lili可以继续达成本人的代码,等egon度蜜月归来后再持续产生类的定义并且去贯彻lili想要的效劳。
一言以蔽之反射的功利就是,能够优先定义好接口,接口唯有在被成功后才会真正举行,那贯彻了即插即用,这实在是一种‘早先时期绑定’,什么意思?即你能够事先把重大的逻辑写好(只定义接口),然后早先时期再去贯彻接口的职能。
1 class FtpClient:
2 'ftp客户端,但是还么有实现具体的功能'
3 def __init__(self,addr):
4 print('正在连接服务器[%s]' %addr)
5 self.addr=addr
6
7 ##############################
8 #不影响lili的代码编写
9
10 from module import FtpClient
11 f1=FtpClient('192.168.1.1')
12 if hasattr(f1,'get'):
13 func_get=getattr(f1,'get')
14 func_get()
15 else:
16 print('---->不存在此方法')
17 print('处理其他的逻辑')
便宜2:动态导入模块(基于反射当前模块成员)
1 #两种导入用户输入模块得方法,官方推荐方法2
2 #方法1
3 m = input('input your module:') #用户输入要导入的模块名,以time模块为例
4 m1 = __import__(m)
5 print(m1) #结果:<module 'time' (built-in)>
6 print(m1.time()) #结果:1493023753.0157707,当前时间
7
8 #方法2
9 import importlib #先导入importlib模块
10 t = importlib.import_module(m)
11 print(t) #结果:<module 'time' (built-in)>
12 print(t.time()) #结果:1493023753.0238242,当前时间
三、内置attr
1 class Foo:
2 x = 1
3 def __init__(self, y):
4 self.y = y
5
6 def __getattr__(self, item):
7 print('----> from getattr:你找的属性不存在')
8
9 def __setattr__(self, key, value):
10 print('----> from setattr')
11 # self.key=value #这就无限递归了
12 self.__dict__[key] = value #应该使用它
13
14 def __delattr__(self, item):
15 print('----> from delattr')
16 # del self.item #无限递归了
17 self.__dict__.pop(item) #应该使用它
18
19 #__setattr__添加/修改属性会触发它的执行
20 f1 = Foo(10) #因为重写了__setattr__,凡是赋值操作都会触发它的运行
21 print(f1.__dict__) #结果:----> from setattr {'y': 10}
22 f1.z = 3 #添加属性
23 print(f1.__dict__) #结果:----> from setattr {'y': 10, 'z': 3}
24
25 #__delattr__删除属性的时候会触发
26 f1.__dict__['a'] = 3 #我们可以直接修改属性字典,来完成添加/修改属性的操作
27 del f1.a #触发__delattr__
28 print(f1.__dict__) #结果:----> from delattr {'y': 10, 'z': 3}
29
30 #__getattr__只有在使用对象调用属性且属性不存在的时候才会触发
31 print(f1.y) #属性存在,结果:10
32 f1.a #属性a不存在,触发__getattr__,结果:----> from getattr:你找的属性不存在
四、三遍加工规范项目(包装)
包装:python为大家提供了专门的事业数据类型,以及丰硕的内置方法,其实在大多面貌下大家都急需依靠职业数据类型来定制我们同甘共苦的数据类型,新扩张/改写方法,那就用到了笔者们刚学的继续/派生知识(其余的规范项目均能够透过下面包车型地铁章程开始展览2次加工)
1 #二次加工标准类型(基于继承实现)
2 class List(list): #继承list所有的属性,也可以派生出自己新的,比如append和mid
3 def append(self, p_object):
4 ' 派生自己的append:加上类型检查'
5 if not isinstance(p_object, int):
6 raise TypeError('must be int')
7 super().append(p_object)
8
9 @property
10 def mid(self):
11 '新增自己的属性'
12 index = len(self)//2
13 return self[index]
14
15 l = List([1, 2, 3, 4])
16 print(l)
17 l.append(5)
18 print(l) #结果:[1, 2, 3, 4, 5]
19 # l.append('1111111') #报错,必须为int类型
20
21 print(l.mid) #结果:3
22
23 #其余的方法都继承list的
24 l.insert(0, -123) #插入元素
25 print(l) #结果:[-123, 1, 2, 3, 4, 5]
26 l.clear() #清空列表
27 print(l) #结果:[]
授权:授权是包装的八个特征, 包装二个品种一般是对已存在的类其余一些定制,那种做法能够新建,修改或删除原有产品的功效。此外的则维持原样。授权的长河,正是全体更新的成效都是由新类的某某些来管理,但已存在的功效就授权给目的的暗中同意属性。
实现授权的关键点便是覆盖__getattr__方法
1 # 授权示范
2 import time
3
4
5 class FileHandle:
6 def __init__(self, filename, mode='r', encoding='utf-8'):
7 self.file = open(filename, mode, encoding=encoding) #获得文件句柄
8
9 def write(self, line): #重新定义write方法,新增添加时间的功能
10 t = time.strftime('%Y-%m-%d %T')
11 self.file.write('%s %s' % (t, line))
12
13 def __getattr__(self, item): #文件操作的其它属性在FileHandle类中找不到时,触发__getattr__
14 return getattr(self.file, item)
15
16
17 f1 = FileHandle('b.txt', 'w+') #新建文件b.txt,获得文件句柄,赋给对象f1
18 f1.write('你好啊') #调用类中的定制方法write
19 f1.seek(0) #重置文件位置于文首,触发__getattr__,正常调用
20 print(f1.read()) #打印文件内容,触发__getattr__,正常调用,结果:2017-04-24 17:30:37 你好啊
21 f1.close() #关闭文件,触发__getattr__,正常调用
参考资料:
1、isinstance(obj, cls) and issubclass(sub, super) 1. isinstance(obj,
cls),检查obj是不是是类cls的目的 一 class A: 2 pass 三 四 obj…
高级
isinstance(obj,cls)和issubclass(sub,super)
isinstance(obj,cls)检查是否obj是不是是类
cls 的靶子
1 class Foo(object):
2 pass
3
4 obj = Foo()
5
6 isinstance(obj, Foo)
issubclass(sub, super)检查sub类是还是不是是
super 类的派生类
1 class Foo(object):
2 pass
3
4 class Bar(Foo):
5 pass
6
7 issubclass(Bar, Foo)
反射:
python面向对象中的反射:通过字符串的方式操作对象相关的习性。python中的一切事物都以目的(都能够利用反射)
# hasattr(object,name)
判断object中有没有一个name字符串对应的方法或属性
# getattr(object, name, default=None)
def getattr(object, name, default=None): # known special case of getattr
"""
getattr(object, name[, default]) -> value
Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""
pass
# setattr(x, y, v)
def setattr(x, y, v): # real signature unknown; restored from __doc__
"""
Sets the named attribute on the given object to the specified value.
setattr(x, 'y', v) is equivalent to ``x.y = v''
"""
pass
# delattr(x, y)
def delattr(x, y): # real signature unknown; restored from __doc__
"""
Deletes the named attribute from the given object.
delattr(x, 'y') is equivalent to ``del x.y''
"""
pass
class BlackMedium:
feature='Ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def sell_house(self):
print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
def rent_house(self):
print('%s 黑中介租房子啦,傻逼才租呢' %self.name)
b1=BlackMedium('万成置地','回龙观天露园')
#检测是否含有某属性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house'))
#获取属性
n=getattr(b1,'name')
print(n)
func=getattr(b1,'rent_house')
func()
# getattr(b1,'aaaaaaaa') #报错
print(getattr(b1,'aaaaaaaa','不存在啊'))
#设置属性
setattr(b1,'sb',True)
setattr(b1,'show_name',lambda self:self.name+'sb')
print(b1.__dict__)
print(b1.show_name(b1))
#删除属性
delattr(b1,'addr')
delattr(b1,'show_name')
delattr(b1,'show_name111')#不存在,则报错
print(b1.__dict__)
方法应用演示
class Foo(object):
staticField = "old boy"
def __init__(self):
self.name = 'wupeiqi'
def func(self):
return 'func'
@staticmethod
def bar():
return 'bar'
print getattr(Foo, 'staticField')
print getattr(Foo, 'func')
print getattr(Foo, 'bar')
类也是目标
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import sys
def s1():
print 's1'
def s2():
print 's2'
this_module = sys.modules[__name__]
hasattr(this_module, 's1')
getattr(this_module, 's2')
反射当前模块成员
导入其余模块,利用反射查找该模块是还是不是留存有个别方法
#!/usr/bin/env python
# -*- coding:utf-8 -*-
def test():
print('from the test')
module_test.py
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3
4 """
5 程序目录:
6 module_test.py
7 index.py
8
9 当前文件:
10 index.py
11 """
12
13 import module_test as obj
14
15 #obj.test()
16
17 print(hasattr(obj,'test'))
18
19 getattr(obj,'test')()
__setattr__,__delattr__,__getattr__
class Foo:
x=1
def __init__(self,y):
self.y=y
def __getattr__(self, item):
print('----> from getattr:你找的属性不存在')
def __setattr__(self, key, value):
print('----> from setattr')
# self.key=value #这就无限递归了,你好好想想
# self.__dict__[key]=value #应该使用它
def __delattr__(self, item):
print('----> from delattr')
# del self.item #无限递归了
self.__dict__.pop(item)
#__setattr__添加/修改属性会触发它的执行
f1=Foo(10)
print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
f1.z=3
print(f1.__dict__)
#__delattr__删除属性的时候会触发
f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__)
#__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx
二遍加工规范项目(包装)
卷入:python为我们提供了正规化数据类型,以及丰裕的嵌入方法,其实在许多景观下大家都须求凭借职业数据类型来定制大家友好的数据类型,新增加/改写方法,那就用到了大家刚学的接续/派生知识(别的的正儿八经项目均可以由此上面包车型地铁不二诀要张开三次加工)
class List(list): #继承list所有的属性,也可以派生出自己新的,比如append和mid
def append(self, p_object):
' 派生自己的append:加上类型检查'
if not isinstance(p_object,int):
raise TypeError('must be int')
super().append(p_object)
@property
def mid(self):
'新增自己的属性'
index=len(self)//2
return self[index]
l=List([1,2,3,4])
print(l)
l.append(5)
print(l)
# l.append('1111111') #报错,必须为int类型
print(l.mid)
#其余的方法都继承list的
l.insert(0,-123)
print(l)
l.clear()
print(l)
二回加工标准项目(基于承继落成)
class List(list):
def __init__(self,item,tag=False):
super().__init__(item)
self.tag=tag
def append(self, p_object):
if not isinstance(p_object,str):
raise TypeError
super().append(p_object)
def clear(self):
if not self.tag:
raise PermissionError
super().clear()
l=List([1,2,3],False)
print(l)
print(l.tag)
l.append('saf')
print(l)
# l.clear() #异常
l.tag=True
l.clear()
练习(clear加权限限制)
授权:授权是包裹的多个本性, 包装1个项目一般是对已存在的体系的一部分定制,那种做法能够新建,修改或删除原有产品的机能。其余的则维持原样。授权的进度,正是全数更新的功用都以由新类的某有些来管理,但已存在的成效就授权给目的的暗中同意属性。
贯彻授权的关键点就是覆盖__getattr__方法
import time
class FileHandle:
def __init__(self,filename,mode='r',encoding='utf-8'):
self.file=open(filename,mode,encoding=encoding)
def write(self,line):
t=time.strftime('%Y-%m-%d %T')
self.file.write('%s %s' %(t,line))
def __getattr__(self, item):
return getattr(self.file,item)
f1=FileHandle('b.txt','w+')
f1.write('你好啊')
f1.seek(0)
print(f1.read())
f1.close()
View Code
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
#我们来加上b模式支持
import time
class FileHandle:
def __init__(self,filename,mode='r',encoding='utf-8'):
if 'b' in mode:
self.file=open(filename,mode)
else:
self.file=open(filename,mode,encoding=encoding)
self.filename=filename
self.mode=mode
self.encoding=encoding
def write(self,line):
if 'b' in self.mode:
if not isinstance(line,bytes):
raise TypeError('must be bytes')
self.file.write(line)
def __getattr__(self, item):
return getattr(self.file,item)
def __str__(self):
if 'b' in self.mode:
res="<_io.BufferedReader name='%s'>" %self.filename
else:
res="<_io.TextIOWrapper name='%s' mode='%s' encoding='%s'>" %(self.filename,self.mode,self.encoding)
return res
f1=FileHandle('b.txt','wb')
# f1.write('你好啊啊啊啊啊') #自定制的write,不用在进行encode转成二进制去写了,简单,大气
f1.write('你好啊'.encode('utf-8'))
print(f1)
f1.close()
View Code
#练习一
class List:
def __init__(self,seq):
self.seq=seq
def append(self, p_object):
' 派生自己的append加上类型检查,覆盖原有的append'
if not isinstance(p_object,int):
raise TypeError('must be int')
self.seq.append(p_object)
@property
def mid(self):
'新增自己的方法'
index=len(self.seq)//2
return self.seq[index]
def __getattr__(self, item):
return getattr(self.seq,item)
def __str__(self):
return str(self.seq)
l=List([1,2,3])
print(l)
l.append(4)
print(l)
# l.append('3333333') #报错,必须为int类型
print(l.mid)
#基于授权,获得insert方法
l.insert(0,-123)
print(l)
#练习二
class List:
def __init__(self,seq,permission=False):
self.seq=seq
self.permission=permission
def clear(self):
if not self.permission:
raise PermissionError('not allow the operation')
self.seq.clear()
def __getattr__(self, item):
return getattr(self.seq,item)
def __str__(self):
return str(self.seq)
l=List([1,2,3])
# l.clear() #此时没有权限,抛出异常
l.permission=True
print(l)
l.clear()
print(l)
#基于授权,获得insert方法
l.insert(0,-123)
print(l)
View Code
__getattribute__
class Foo:
def __init__(self,x):
self.x=x
def __getattr__(self, item):
print('执行的是我')
# return self.__dict__[item]
f1=Foo(10)
print(f1.x)
f1.xxxxxx #不存在的属性访问,触发__getattr__
getattr
class Foo:
def __init__(self,x):
self.x=x
def __getattribute__(self, item):
print('不管是否存在,我都会执行')
f1=Foo(10)
f1.x
f1.xxxxxx
__getattribute__
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
class Foo:
def __init__(self,x):
self.x=x
def __getattr__(self, item):
print('执行的是我')
# return self.__dict__[item]
def __getattribute__(self, item):
print('不管是否存在,我都会执行')
raise AttributeError('哈哈')
f1=Foo(10)
f1.x
f1.xxxxxx
#当__getattribute__与__getattr__同时存在,只会执行__getattrbute__,除非__getattribute__在执行过程中抛出异常AttributeError
而且出现
描述符(__get__,__set__,__delete__)
讲述符是什么:描述符本质便是三个新式类,在那个新型类中,至少落成了__get__(),__set__(),__delete__()中的3个,那也被叫做描述符协议
__get__():调用叁个属性时,触发
__set__():为二天性质赋值时,触发
__delete__():选拔del删除属性时,触发
class Foo: #在python3中Foo是新式类,它实现了三种方法,这个类就被称作一个描述符
def __get__(self, instance, owner):
pass
def __set__(self, instance, value):
pass
def __delete__(self, instance):
pass
概念描述符
叙述符的效益是用来代理此外三个类的性质的(必须把描述符定义成那些类的类属性,无法定义到构造函数中)
class Foo:
def __get__(self, instance, owner):
print('触发get')
def __set__(self, instance, value):
print('触发set')
def __delete__(self, instance):
print('触发delete')
#包含这三个方法的新式类称为描述符,由这个类产生的实例进行属性的调用/赋值/删除,并不会触发这三个方法
f1=Foo()
f1.name='egon'
f1.name
del f1.name
#疑问:何时,何地,会触发这三个方法的执行
引子:描述符类发生的实例实行品质操作并不会触发几个办法的实施
#描述符Str
class Str:
def __get__(self, instance, owner):
print('Str调用')
def __set__(self, instance, value):
print('Str设置...')
def __delete__(self, instance):
print('Str删除...')
#描述符Int
class Int:
def __get__(self, instance, owner):
print('Int调用')
def __set__(self, instance, value):
print('Int设置...')
def __delete__(self, instance):
print('Int删除...')
class People:
name=Str()
age=Int()
def __init__(self,name,age): #name被Str类代理,age被Int类代理,
self.name=name
self.age=age
#何地?:定义成另外一个类的类属性
#何时?:且看下列演示
p1=People('alex',18)
#描述符Str的使用
p1.name
p1.name='egon'
del p1.name
#描述符Int的使用
p1.age
p1.age=18
del p1.age
#我们来瞅瞅到底发生了什么
print(p1.__dict__)
print(People.__dict__)
#补充
print(type(p1) == People) #type(obj)其实是查看obj是由哪个类实例化来的
print(type(p1).__dict__ == People.__dict__)
叙述符应用之哪天?哪个地点?
描述符分三种
1数量描述符:至少完结了__get__()和__set__()
1 class Foo:
2 def __set__(self, instance, value):
3 print('set')
4 def __get__(self, instance, owner):
5 print('get')
非数据描述符:未有落到实处__set__()
1 class Foo:
2 def __get__(self, instance, owner):
3 print('get')
注意事项:
1描述符自个儿应当定义成新式类,被代理的类也应该是新型类
二必须把描述符定义成那么些类的类属性,不可能为定义到构造函数中
3要严加依照该优先级,优先级由高到底分别是
1.类属性
二.多少描述符
面向对象进阶,python面向对象编制程序。三.实例属性
肆.非数目描述符
5.找不到的质量触发__getattr__()
#描述符Str
class Str:
def __get__(self, instance, owner):
print('Str调用')
def __set__(self, instance, value):
print('Str设置...')
def __delete__(self, instance):
print('Str删除...')
class People:
name=Str()
def __init__(self,name,age): #name被Str类代理,age被Int类代理,
self.name=name
self.age=age
#基于上面的演示,我们已经知道,在一个类中定义描述符它就是一个类属性,存在于类的属性字典中,而不是实例的属性字典
#那既然描述符被定义成了一个类属性,直接通过类名也一定可以调用吧,没错
People.name #恩,调用类属性name,本质就是在调用描述符Str,触发了__get__()
People.name='egon' #那赋值呢,我去,并没有触发__set__()
del People.name #赶紧试试del,我去,也没有触发__delete__()
#结论:描述符对类没有作用-------->傻逼到家的结论
'''
原因:描述符在使用时被定义成另外一个类的类属性,因而类属性比二次加工的描述符伪装而来的类属性有更高的优先级
People.name #恩,调用类属性name,找不到就去找描述符伪装的类属性name,触发了__get__()
People.name='egon' #那赋值呢,直接赋值了一个类属性,它拥有更高的优先级,相当于覆盖了描述符,肯定不会触发描述符的__set__()
del People.name #同上
'''
类属性>数据描述符
#描述符Str
class Str:
def __get__(self, instance, owner):
print('Str调用')
def __set__(self, instance, value):
print('Str设置...')
def __delete__(self, instance):
print('Str删除...')
class People:
name=Str()
def __init__(self,name,age): #name被Str类代理,age被Int类代理,
self.name=name
self.age=age
p1=People('egon',18)
#如果描述符是一个数据描述符(即有__get__又有__set__),那么p1.name的调用与赋值都是触发描述符的操作,于p1本身无关了,相当于覆盖了实例的属性
p1.name='egonnnnnn'
p1.name
print(p1.__dict__)#实例的属性字典中没有name,因为name是一个数据描述符,优先级高于实例属性,查看/赋值/删除都是跟描述符有关,与实例无关了
del p1.name
多少描述符>实例属性
class Foo:
def func(self):
print('我胡汉三又回来了')
f1=Foo()
f1.func() #调用类的方法,也可以说是调用非数据描述符
#函数是一个非数据描述符对象(一切皆对象么)
print(dir(Foo.func))
print(hasattr(Foo.func,'__set__'))
print(hasattr(Foo.func,'__get__'))
print(hasattr(Foo.func,'__delete__'))
#有人可能会问,描述符不都是类么,函数怎么算也应该是一个对象啊,怎么就是描述符了
#笨蛋哥,描述符是类没问题,描述符在应用的时候不都是实例化成一个类属性么
#函数就是一个由非描述符类实例化得到的对象
#没错,字符串也一样
f1.func='这是实例属性啊'
print(f1.func)
del f1.func #删掉了非数据
f1.func()
实例属性>非数据描述符
class Foo:
def __set__(self, instance, value):
print('set')
def __get__(self, instance, owner):
print('get')
class Room:
name=Foo()
def __init__(self,name,width,length):
self.name=name
self.width=width
self.length=length
#name是一个数据描述符,因为name=Foo()而Foo实现了get和set方法,因而比实例属性有更高的优先级
#对实例的属性操作,触发的都是描述符的
r1=Room('厕所',1,1)
r1.name
r1.name='厨房'
class Foo:
def __get__(self, instance, owner):
print('get')
class Room:
name=Foo()
def __init__(self,name,width,length):
self.name=name
self.width=width
self.length=length
#name是一个非数据描述符,因为name=Foo()而Foo没有实现set方法,因而比实例属性有更低的优先级
#对实例的属性操作,触发的都是实例自己的
r1=Room('厕所',1,1)
r1.name
r1.name='厨房'
再也应验:实例属性>非数据描述符
class Foo:
def func(self):
print('我胡汉三又回来了')
def __getattr__(self, item):
print('找不到了当然是来找我啦',item)
f1=Foo()
f1.xxxxxxxxxxx
非数据描述符>找不到
讲述符总结
讲述符是能够达成繁多python类天性中的底层法力,包蕴@classmethod,@staticmethd,@property乃至是__slots__属性
讲述父是大多高端库和框架的根本工具之一,描述符平常是采用到装饰器或许元类的巨型框架中的贰个组件.
使用描述符原理完结八个自定制@classmethod
class ClassMethod:
def __init__(self,func):
self.func=func
def __get__(self, instance, owner): #类来调用,instance为None,owner为类本身,实例来调用,instance为实例,owner为类本身,
def feedback():
print('在这里可以加功能啊...')
return self.func(owner)
return feedback
class People:
name='linhaifeng'
@ClassMethod # say_hi=ClassMethod(say_hi)
def say_hi(cls):
print('你好啊,帅哥 %s' %cls.name)
People.say_hi()
p1=People()
p1.say_hi()
#疑问,类方法如果有参数呢,好说,好说
class ClassMethod:
def __init__(self,func):
self.func=func
def __get__(self, instance, owner): #类来调用,instance为None,owner为类本身,实例来调用,instance为实例,owner为类本身,
def feedback(*args,**kwargs):
print('在这里可以加功能啊...')
return self.func(owner,*args,**kwargs)
return feedback
class People:
name='linhaifeng'
@ClassMethod # say_hi=ClassMethod(say_hi)
def say_hi(cls,msg):
print('你好啊,帅哥 %s %s' %(cls.name,msg))
People.say_hi('你是那偷心的贼')
p1=People()
p1.say_hi('你是那偷心的贼')
@classmethod
采取描述符原理达成三个自定制的@staticmethod
class StaticMethod:
def __init__(self,func):
self.func=func
def __get__(self, instance, owner): #类来调用,instance为None,owner为类本身,实例来调用,instance为实例,owner为类本身,
def feedback(*args,**kwargs):
print('在这里可以加功能啊...')
return self.func(*args,**kwargs)
return feedback
class People:
@StaticMethod# say_hi=StaticMethod(say_hi)
def say_hi(x,y,z):
print('------>',x,y,z)
People.say_hi(1,2,3)
p1=People()
p1.say_hi(4,5,6)
@staticmethod
property
贰个静态属性property本质就是落成了get,set,delete三种方法
class Foo:
@property
def AAA(self):
print('get的时候运行我啊')
@AAA.setter
def AAA(self,value):
print('set的时候运行我啊')
@AAA.deleter
def AAA(self):
print('delete的时候运行我啊')
#只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA
用法1
class Foo:
def get_AAA(self):
print('get的时候运行我啊')
def set_AAA(self,value):
print('set的时候运行我啊')
def delete_AAA(self):
print('delete的时候运行我啊')
AAA=property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应
f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA
用法2
例子
class Goods:
def __init__(self):
# 原价
self.original_price = 100
# 折扣
self.discount = 0.8
@property
def price(self):
# 实际价格 = 原价 * 折扣
new_price = self.original_price * self.discount
return new_price
@price.setter
def price(self, value):
self.original_price = value
@price.deleter
def price(self):
del self.original_price
obj = Goods()
obj.price # 获取商品价格
obj.price = 200 # 修改商品原价
print(obj.price)
del obj.price # 删除商品原价
例子1
#实现类型检测功能
#第一关:
class People:
def __init__(self,name):
self.name=name
@property
def name(self):
return self.name
# p1=People('alex') #property自动实现了set和get方法属于数据描述符,比实例属性优先级高,所以你这面写会触发property内置的set,抛出异常
#第二关:修订版
class People:
def __init__(self,name):
self.name=name #实例化就触发property
@property
def name(self):
# return self.name #无限递归
print('get------>')
return self.DouNiWan
@name.setter
def name(self,value):
print('set------>')
self.DouNiWan=value
@name.deleter
def name(self):
print('delete------>')
del self.DouNiWan
p1=People('alex') #self.name实际是存放到self.DouNiWan里
print(p1.name)
print(p1.name)
print(p1.name)
print(p1.__dict__)
p1.name='egon'
print(p1.__dict__)
del p1.name
print(p1.__dict__)
#第三关:加上类型检查
class People:
def __init__(self,name):
self.name=name #实例化就触发property
@property
def name(self):
# return self.name #无限递归
print('get------>')
return self.DouNiWan
@name.setter
def name(self,value):
print('set------>')
if not isinstance(value,str):
raise TypeError('必须是字符串类型')
self.DouNiWan=value
@name.deleter
def name(self):
print('delete------>')
del self.DouNiWan
p1=People('alex') #self.name实际是存放到self.DouNiWan里
p1.name=1
例子2
item家族
class Foo:
def __init__(self,name):
self.name=name
def __getitem__(self, item):
print(self.__dict__[item])
def __setitem__(self, key, value):
self.__dict__[key]=value
def __delitem__(self, key):
print('del obj[key]时,我执行')
self.__dict__.pop(key)
def __delattr__(self, item):
print('del obj.key时,我执行')
self.__dict__.pop(item)
f1=Foo('sb')
f1['age']=18
f1['age1']=19
del f1.age1
del f1['age']
f1['name']='alex'
print(f1.__dict__)
__str__,__repr__,__format__
转移目的的字符串显示__str__,__repr__
自定制格式化字符串__format__
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
format_dict={
'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
}
class School:
def __init__(self,name,addr,type):
self.name=name
self.addr=addr
self.type=type
def __repr__(self):
return 'School(%s,%s)' %(self.name,self.addr)
def __str__(self):
return '(%s,%s)' %(self.name,self.addr)
def __format__(self, format_spec):
# if format_spec
if not format_spec or format_spec not in format_dict:
format_spec='nat'
fmt=format_dict[format_spec]
return fmt.format(obj=self)
s1=School('oldboy1','北京','私立')
print('from repr: ',repr(s1))
print('from str: ',str(s1))
print(s1)
'''
str函数或者print函数--->obj.__str__()
repr或者交互式解释器--->obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__来代替输出
注意:这俩方法的返回值必须是字符串,否则抛出异常
'''
print(format(s1,'nat'))
print(format(s1,'tna'))
print(format(s1,'tan'))
print(format(s1,'asfdasdffd'))
例子
date_dic={
'ymd':'{0.year}:{0.month}:{0.day}',
'dmy':'{0.day}/{0.month}/{0.year}',
'mdy':'{0.month}-{0.day}-{0.year}',
}
class Date:
def __init__(self,year,month,day):
self.year=year
self.month=month
self.day=day
def __format__(self, format_spec):
if not format_spec or format_spec not in date_dic:
format_spec='ymd'
fmt=date_dic[format_spec]
return fmt.format(self)
d1=Date(2016,12,29)
print(format(d1))
print('{:mdy}'.format(d1))
例子2
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
class A:
pass
class B(A):
pass
print(issubclass(B,A)) #B是A的子类,返回True
a1=A()
print(isinstance(a1,A)) #a1是A的实例
issubclass和isinstance
__slots__
'''
1.__slots__是什么:是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性)
2.引子:使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的)
3.为何使用__slots__:字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__
当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个
字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给
实例添加新的属性了,只能使用在__slots__中定义的那些属性名。
4.注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。另外,定义了__slots__后的类不再 支持一些普通类特性了,比如多继承。大多数情况下,你应该
只在那些经常被使用到 的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象 。
关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。 更多的是用来作为一个内存优化工具。
'''
class Foo:
__slots__='x'
f1=Foo()
f1.x=1
f1.y=2#报错
print(f1.__slots__) #f1不再有__dict__
class Bar:
__slots__=['x','y']
n=Bar()
n.x,n.y=1,2
n.z=3#报错
例子
class Foo:
__slots__=['name','age']
f1=Foo()
f1.name='alex'
f1.age=18
print(f1.__slots__)
f2=Foo()
f2.name='egon'
f2.age=19
print(f2.__slots__)
print(Foo.__dict__)
#f1与f2都没有属性字典__dict__了,统一归__slots__管,节省内存
例子2
__next__和__iter__兑现迭代器协议
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
class Foo:
def __init__(self,x):
self.x=x
def __iter__(self):
return self
def __next__(self):
n=self.x
self.x+=1
return self.x
f=Foo(3)
for i in f:
print(i)
例子1
class Range:
def __init__(self,n,stop,step):
self.n=n
self.stop=stop
self.step=step
def __next__(self):
if self.n >= self.stop:
raise StopIteration
x=self.n
self.n+=self.step
return x
def __iter__(self):
return self
for i in Range(1,7,3): #
print(i)
模拟range
class Fib:
def __init__(self):
self._a=0
self._b=1
def __iter__(self):
return self
def __next__(self):
self._a,self._b=self._b,self._a + self._b
return self._a
f1=Fib()
print(f1.__next__())
print(next(f1))
print(next(f1))
for i in f1:
if i > 100:
break
print('%s ' %i,end='')
斐波这契数列
__del__
析构方法,当目标在内部存款和储蓄器中被假释时,自动触发施行。
注:如若发生的靶子仅仅只是python程序级其余(用户级),那么无需定义__del__,假使爆发的目的的还要还会向操作系统一发布起系统调用,即1个对象有用户级与内核级三种财富,比方(张开2个文书,创设3个数据库链接),则必须在摒除对象的同时回收系统资源,这就用到了__del__
class Foo:
def __del__(self):
print('执行我啦')
f1=Foo()
del f1
print('------->')
#输出结果
执行我啦
------->
优良的利用场景:
创造数量库类,用该类实例化出数据库链接对象,对象自己是存放于用户空间内部存储器中,而链接则是由操作系统管理的,存放于内核空间内部存款和储蓄器中
当程序甘休时,python只会回收本身的内部存款和储蓄器空间,即用户态内部存款和储蓄器,而操作系统的能源则从未被回收,那就必要大家定制__del__,在目标被剔除前向操作系统发起关闭数据库链接的系统调用,回收财富
__enter__和__exit__
1 with open('a.txt') as f:
2 '代码块
上述叫做上下文处理协议,即with语句,为了让三个目的包容with语句,必须在这些目标的类中阐明__enter__和__exit__方法
class Open:
def __init__(self,name):
self.name=name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
# return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
with Open('a.txt') as f:
print('=====>执行代码块')
# print(f,f.name)
上下文管理协议
__exit__()中的八个参数分别表示丰盛类型,分外值和追溯消息,with语句中代码块出现至极,则with后的代码都无法实践
class Open:
def __init__(self,name):
self.name=name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
print(exc_type)
print(exc_val)
print(exc_tb)
with Open('a.txt') as f:
print('=====>执行代码块')
raise AttributeError('***着火啦,救火啊***')
print('0'*100) #------------------------------->不会执行
class Open:
def __init__(self,filepath,mode='r',encoding='utf-8'):
self.filepath=filepath
self.mode=mode
self.encoding=encoding
def __enter__(self):
# print('enter')
self.f=open(self.filepath,mode=self.mode,encoding=self.encoding)
return self.f
def __exit__(self, exc_type, exc_val, exc_tb):
# print('exit')
self.f.close()
return True
def __getattr__(self, item):
return getattr(self.f,item)
with Open('a.txt','w') as f:
print(f)
f.write('aaaaaa')
f.wasdf #抛出异常,交给__exit__处理
模拟open
用途大概说好处:
壹.用到with语句的目标就是把代码块放入with中实行,with结束后,自动完结清理专门的学问,无须手动干预
二.在须要管住一些能源比方文件,网络连接和锁的编制程序景况中,能够在__exit__中定制自动释放财富的机制,你无须再去关系那个标题,那将大有用处
__call__
对象前面加括号,触发实行。
注:构造方法的实行是由创立对象触发的,即:对象 = 类名() ;而对此
__call__ 方法的实践是由对象后加括号触发的,即:对象() 也许 类()()
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行 __init__
obj() # 执行 __call__
__new__,__len__,__hash__
class A:
def __init__(self):
self.x = 1
print('in init function')
def __new__(cls, *args, **kwargs):
print('in new function')
return object.__new__(A, *args, **kwargs)
a = A()
print(a.x)
# ---------------单例模式
class Singleton:
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance
one = Singleton()
two = Singleton()
two.a = 3
print(one.a)
# 3
# one和two完全相同,可以用id(), ==, is检测
print(id(one))
# 29097904
print(id(two))
# 29097904
print(one == two)
# True
print(one is two)
__new__
class A:
def __init__(self):
self.a = 1
self.b = 2
def __len__(self):
return len(self.__dict__)
a = A()
print(len(a))
__len__
class A:
def __init__(self):
self.a = 1
self.b = 2
def __hash__(self):
return hash(str(self.a)+str(self.b))
a = A()
print(hash(a))
__hash__
__eq__
class A:
def __init__(self):
self.a = 1
self.b = 2
def __eq__(self,obj):
if self.a == obj.a and self.b == obj.b:
return True
a = A()
b = A()
print(a == b)
例子
# 有100个对象在列表里,去重
class Person:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def __hash__(self):
return hash(self.name+self.sex)
def __eq__(self, other):
if self.name == other.name and self.sex == other.sex:return True
p_lst = []
for i in range(84):
p_lst.append(Person('egon',i,'male'))
print(p_lst)
print(set(p_lst))
面试题
class FranchDeck:
ranks = [str(n) for n in range(2,11)] + list('JQKA')
suits = ['红心','方板','梅花','黑桃']
def __init__(self):
self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
for suit in FranchDeck.suits]
def __len__(self):
return len(self._cards)
def __getitem__(self, item):
return self._cards[item]
deck = FranchDeck()
print(deck[0])
from random import choice
print(choice(deck))
print(choice(deck))
叶子游戏
一 isinstance(obj,cls)和issubclass(sub,super)
isinstance(obj,cls)检查是不是obj是还是不是是类 cls
的目标
1 class Foo(object):
2 pass
3
4 obj = Foo()
5
6 isinstance(obj, Foo)
issubclass(sub,
super)检查sub类是或不是是 super 类的派生类
class Foo(object):
pass
class Bar(Foo):
pass
issubclass(Bar, Foo)
二、反射
2python面向对象中的反射:通过字符串的款型操作对象相关的性质。python中的1切事物皆以目的(都能够选用反射)
三个能够完成自省的函数
def getattr(object ,
name, defalut=None) :
判断object中有没有一个name字符串对应的方法或属性
def getattr(object, name, default=None): # known special case of getattr
"""
getattr(object, name[, default]) -> value
Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""
pass
def setattr(x,y, v):
def setattr(x, y, v): # real signature unknown; restored from __doc__
"""
Sets the named attribute on the given object to the specified value.
setattr(x, 'y', v) is equivalent to ``x.y = v''
"""
pass
def delattr(x,y):
def delattr(x, y): # real signature unknown; restored from __doc__
"""
Deletes the named attribute from the given object.
delattr(x, 'y') is equivalent to ``del x.y''
"""
pass
实施案例
class BlackMedium:
feature='Ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def sell_house(self):
print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
def rent_house(self):
print('%s 黑中介租房子啦,傻逼才租呢' %self.name)
b1=BlackMedium('万成置地','回龙观天露园')
#检测是否含有某属性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house'))
#获取属性
n=getattr(b1,'name')
print(n)
func=getattr(b1,'rent_house')
func()
# getattr(b1,'aaaaaaaa') #报错
print(getattr(b1,'aaaaaaaa','不存在啊'))
#设置属性
setattr(b1,'sb',True)
setattr(b1,'show_name',lambda self:self.name+'sb')#给Blackhouser添加SB属性
print(b1.__dict__)
print(b1.show_name(b1))
#删除属性
delattr(b1,'addr')
delattr(b1,'show_name')
delattr(b1,'show_name111')#不存在,则报错
print(b1.__dict__)
类也是对象
class Foo(object):
staticField = "old boy"
def __init__(self):
self.name = 'wupeiqi'
def func(self):
return 'func'
@staticmethod
def bar():
return 'bar'
print getattr(Foo, 'staticField')
print getattr(Foo, 'func')
print getattr(Foo, 'bar')
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import sys
def s1():
print 's1'
def s2():
print 's2'
this_module = sys.modules[__name__]
hasattr(this_module, 's1')
getattr(this_module, 's2')
#!/usr/bin/env python
# -*- coding:utf-8 -*-
def test():
print('from the test')
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3
4 """
5 程序目录:
6 module_test.py
7 index.py
8
9 当前文件:
10 index.py
11 """
12
13 import module_test as obj
14
15 #obj.test()
16
17 print(hasattr(obj,'test'))
18
19 getattr(obj,'test')()
View Code
3为何用反射之反射的好处
便宜一:完毕可插拔机制
简单的说反射的益处是,能够预先定义好接口,接口唯有在被成功后才会真正施行,那贯彻了即插即用,那实在是一种‘中期绑定’,什么看头?即你可以预先把第一的逻辑写好(只定义接口),然后早先时期再去落成接口的成效
class FtpClient:
'ftp客户端,但是还么有实现具体的功能'
def __init__(self,addr):
print('正在连接服务器[%s]' %addr)
self.addr=addr
#from module import FtpClient
f1=FtpClient('192.168.1.1')
if hasattr(f1,'get'):
func_get=getattr(f1,'get')
func_get()
else:
print('---->不存在此方法')
print('处理其他的逻辑')
动态导入模块
一 isinstance(obj,cls)和issubclass(sub,super)
isinstance(obj,cls)检查是还是不是obj是或不是是类 cls 的目的
1 class Foo(object):
2 pass
3
4 obj = Foo()
5
6 isinstance(obj, Foo)
issubclass(sub, super)检查sub类是或不是是 super 类的派生类
class Foo(object):
pass
class Bar(Foo):
pass
issubclass(Bar, Foo)
二、反射
二python面向对象中的反射:通过字符串的花样操作对象相关的天性。python中的1切事物都以目的(都足以选取反射)
七个能够达成自省的函数
def getattr(object , name, defalut=None) :
判断object中有没有一个name字符串对应的方法或属性
def getattr(object, name, default=None): # known special case of getattr
"""
getattr(object, name[, default]) -> value
Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""
pass
def setattr(x,y, v):
def setattr(x, y, v): # real signature unknown; restored from __doc__
"""
Sets the named attribute on the given object to the specified value.
setattr(x, 'y', v) is equivalent to ``x.y = v''
"""
pass
def delattr(x,y):
def delattr(x, y): # real signature unknown; restored from __doc__
"""
Deletes the named attribute from the given object.
delattr(x, 'y') is equivalent to ``del x.y''
"""
pass
奉行案例
class BlackMedium:
feature='Ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def sell_house(self):
print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
def rent_house(self):
print('%s 黑中介租房子啦,傻逼才租呢' %self.name)
b1=BlackMedium('万成置地','回龙观天露园')
#检测是否含有某属性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house'))
#获取属性
n=getattr(b1,'name')
print(n)
func=getattr(b1,'rent_house')
func()
# getattr(b1,'aaaaaaaa') #报错
print(getattr(b1,'aaaaaaaa','不存在啊'))
#设置属性
setattr(b1,'sb',True)
setattr(b1,'show_name',lambda self:self.name+'sb')#给Blackhouser添加SB属性
print(b1.__dict__)
print(b1.show_name(b1))
#删除属性
delattr(b1,'addr')
delattr(b1,'show_name')
delattr(b1,'show_name111')#不存在,则报错
print(b1.__dict__)
类也是对象
class Foo(object):
staticField = "old boy"
def __init__(self):
self.name = 'wupeiqi'
def func(self):
return 'func'
@staticmethod
def bar():
return 'bar'
print getattr(Foo, 'staticField')
print getattr(Foo, 'func')
print getattr(Foo, 'bar')
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import sys
def s1():
print 's1'
def s2():
print 's2'
this_module = sys.modules[__name__]
hasattr(this_module, 's1')
getattr(this_module, 's2')
#!/usr/bin/env python
# -*- coding:utf-8 -*-
def test():
print('from the test')
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3
4 """
5 程序目录:
6 module_test.py
7 index.py
8
9 当前文件:
10 index.py
11 """
12
13 import module_test as obj
14
15 #obj.test()
16
17 print(hasattr(obj,'test'))
18
19 getattr(obj,'test')()
View Code
3 为何用反射之反射的功利
便宜一:完结可插拔机制
不问可见反射的便宜是,能够先行定义好接口,接口唯有在被成功后才会真的实践,那贯彻了即插即用,这其实是一种‘早先时期绑定’,什么意思?即你能够先行把关键的逻辑写好(只定义接口),然后前期再去贯彻接口的成效
class FtpClient:
'ftp客户端,但是还么有实现具体的功能'
def __init__(self,addr):
print('正在连接服务器[%s]' %addr)
self.addr=addr
#from module import FtpClient
f1=FtpClient('192.168.1.1')
if hasattr(f1,'get'):
func_get=getattr(f1,'get')
func_get()
else:
print('---->不存在此方法')
print('处理其他的逻辑')
动态导入模块
三 __setattr__,__delattr__,__getattr__
class Foo:
x=1
def __init__(self,y):
self.y=y
def __getattr__(self, item):
print('----> from getattr:你找的属性不存在')
def __setattr__(self, key, value):
print('----> from setattr')
# self.key=value #这就无限递归了,你好好想想
# self.__dict__[key]=value #应该使用它
def __delattr__(self, item):
print('----> from delattr')
# del self.item #无限递归了
self.__dict__.pop(item)
#__setattr__添加/修改属性会触发它的执行
f1=Foo(10)
print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
f1.z=3
print(f1.__dict__)
#__delattr__删除属性的时候会触发
f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__)
#__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx
三 __setattr__,__金沙注册送58,delattr__,__getattr__
class Foo:
x=1
def __init__(self,y):
self.y=y
def __getattr__(self, item):
print('----> from getattr:你找的属性不存在')
def __setattr__(self, key, value):
print('----> from setattr')
# self.key=value #这就无限递归了,你好好想想
# self.__dict__[key]=value #应该使用它
def __delattr__(self, item):
print('----> from delattr')
# del self.item #无限递归了
self.__dict__.pop(item)
#__setattr__添加/修改属性会触发它的执行
f1=Foo(10)
print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
f1.z=3
print(f1.__dict__)
#__delattr__删除属性的时候会触发
f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__)
#__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx
四 一回加工标准项目(包装)
装进:python为大家提供了规范数据类型,以及足够的放到方法,其实在不少场景下大家都须要依据职业数据类型来定制大家自个儿的数据类型,新扩展/改写方法,那就用到了大家刚学的延续/派生知识(别的的正式项目均能够通过下边包车型客车办法实行一回加工)
授权:授权是包装的三个个性, 包装3个门类一般是对已存在的类型的一部分定制,那种做法得以新建,修改或删除原有产品的法力。其它的则维持原样。授权的进度,就是全体更新的作用都是由新类的某部分来处理,但已存在的效率就授权给目标的暗中认可属性。
贯彻授权的关键点正是覆盖__getattr__方法
import time
class FileHandle:
def __init__(self,filename,mode='r',encoding='utf-8'):
self.file=open(filename,mode,encoding=encoding)
def write(self,line):
t=time.strftime('%Y-%m-%d %T')
self.file.write('%s %s' %(t,line))
def __getattr__(self, item):
return getattr(self.file,item)
f1=FileHandle('b.txt','w+')
f1.write('你好啊')
f1.seek(0)
print(f1.read())
f1.close()
讲述符注意事项:
一描述符自己应当定义成新式类,被代理的类也相应是风靡类
二必须把描述符定义成这几个类的类属性,不可能为定义到构造函数中
叁要严格遵照该优先级,优先级由高到底分别是
1.类属性
二.数码描述符
三.实例属性
四.非数据描述符
伍.找不到的本性触发__getattr__()
其中
数据描述符、数据描述符:至少完结了__get__()和__set__()
非数据描述符、未有落到实处__set__()
四 一回加工标准项目(包装)
卷入:python为大家提供了业内数据类型,以及充足的放置方法,其实在不少场景下我们都急需基于专门的学业数据类型来定制我们和好的数据类型,新扩展/改写方法,那就用到了我们刚学的延续/派生知识(其余的正规项目均能够经过上边包车型地铁法子进行二遍加工)
授权:授权是包装的四个特点, 包装3个品类一般是对已存在的品类的局地定制,那种做法得以新建,修改或删除原有产品的职能。其余的则维持原样。授权的进程,便是全数更新的效率都以由新类的某部分来拍卖,但已存在的功力就授权给目的的暗中同意属性。
兑现授权的关键点正是覆盖__getattr__方法
import time
class FileHandle:
def __init__(self,filename,mode='r',encoding='utf-8'):
self.file=open(filename,mode,encoding=encoding)
def write(self,line):
t=time.strftime('%Y-%m-%d %T')
self.file.write('%s %s' %(t,line))
def __getattr__(self, item):
return getattr(self.file,item)
f1=FileHandle('b.txt','w+')
f1.write('你好啊')
f1.seek(0)
print(f1.read())
f1.close()
讲述符注意事项:
一 描述符自个儿应当定义成新式类,被代理的类也应当是流行类
2 必须把描述符定义成那个类的类属性,无法为定义到构造函数中
3 要严加坚守该优先级,优先级由高到底分别是
1.类属性
2.数码描述符
3.实例属性
四.非多少描述符
5.找不到的性质触发__getattr__()
其中
数量描述符、数据描述符:至少达成了__get__()和__set__()
非数据描述符、没有得以达成__set__()
一isinstance(obj,cls)和issubclass(sub,super) i
sinstance(obj,cls)检查是还是不是obj是不是是类 cls 的目的 一 class Foo(object): 二pass 3 四 obj = Foo(…