- 文件也是对象,也可以用反射模块中的四个方法
- 在团队协作中,可插拔机制,使用反射方法判断下模块中是否有对应的函数
- 导入就是将文件拿过来,在当前文件中执行一遍
-
#导入其他模块用import as的方法,想在模块自身应用反射方法,需要通过以下语句方法来导入模块本身,然后应用反射的方法
import sys
obj1=sys.modules[__name__]#__name__是当前模块名,sys.modules通过key的方法能取到当前模块
print('==>',hasattr(obj1,'x'))
-
内置函数补充
- isinstance(obj,cls)判断一个对象obj是否为某类class本身或子类生成的实例
- issubclass(sub,super)判断sub是否为super的子类
- type(b1)显示实例b1所属的类
- !没啥用__getattribute__:属性存在,返回匹配的值。属性不存在,抛出一个异常
-
class Foo:
def __init__(self,x):
self.x=x
def __getattr__(self, item):
print('执行的是getattr')
def __getattribute__(self, item):#甭管属性是否能找到,都会触发此,
print('执行的是getattribute')
raise AttributeError('抛出异常了')#在此抛出这个指令的情况下,才会触发getattr
f1=Foo(10)
# f1.x
f1.xxxxx
-
item系列
-
#.的调用方式跟getattr等三个方法相关,字典形式的操作跟getitem等三个方法相关
class Foo:
def __getitem__(self, item):
print('getitem')
return self.__dict__[item]
def __setitem__(self, key, value):
print('setitem')
self.__dict__[key] = value # 模拟字典新增键值对的方法
def __delitem__(self, key):
print('delitem')
self.__dict__.pop(key)
f1 = Foo()
print(f1.__dict__)
# f1.name='egon'#这种方式不会触发setitem
f1['name'] = 'egon' # 按照字典方式赋值,会触发setitem方法,字典是['属性']的形式
f1['age'] = 18
print(f1.__dict__)
del f1.name # 通过.的方式,跟delattr那种方式匹配,不匹配delitem的方式
print(f1.__dict__)
-
str方法:改变对象的字符串显示
- 一切皆对象,打印时本质都应该是object,有些对象的打印结果不是object。表明可以在自己的类中定制一些方法,来控制该类实例出的对象输出结果是什么形式
-
class Foo:
#类中有默认的str方法,如果不自定义,则采用系统的
def __str__(self):#自定义该类实例的对象的打印结果
return '自定制的对象的显示方式'#必须return字符串类型
f1=Foo()
print(f1)#本质是就调用的--str(f1)--方法,就是f1.__str__()方法
-
#在解释器中用__repr__
class Foo:
#类中有默认的str方法,如果不自定义,则采用系统的
def __str__(self):
return '这是str'
def __repr__(self):#自定义该类实例的对象的打印结果
return '名字是%s 年龄是%s'%(self.name,self.age)
#不能return非字符串格式
f1=Foo()
#在解释器中输入f1#本质是就调用的--repr(f1)--方法,就是f1.__repr__()方法
print(f1)#如果有str就找str,如无,则找repr。如都无,则找系统内置的
-
为实例定制format
-
format_dic = {
'ymd': '{0.year}{0.mon}{0.day}',
'm-d-y': '{0.mon}-{0.day}-{0.year}',
'y:m:d': '{0.year}:{0.mon}:{0.day}'
}
class Date:
def __init__(self, year, mon, day):
self.year = year
self.mon = mon
self.day = day
def __format__(self, format_spec):
print('我执行啦')
print('-->', format_spec)
if not format_spec or format_spec not in format_dic:
format_spec = 'ymd'
fm = format_dic[format_spec]
return fm.format(self)
d1 = Date(2016, 12, 26)
# format(d1)
print(format(d1, 'y:m:d'))
-
slots属性
- _solts_是一个类变量,变量值可以是列表,元组或者可迭代对象,也可以是字符串(意味着所有实例只有一个数据属性)
- 类的字典是共享的,供该类产生的实例调用
- 当类的属性很少,但是需要产生成千上万的实例时,每个实例都有独立的存储空间,很浪费内存
- _slots_上场后,每个实例不再有_dict_,这样不用为每个实例创建属性字典,节省内存空间
-
class Foo:
# __slots__ = ['name','age']
__slots__ = 'name' # 不用每个实例创建属性字典,统一到类属性字典中找
# 缺点:每个实例只能创建一个name的属性,不能创建其他属性
# 优势所在是省内存,而不是处于限制实例扩展属性
f1 = Foo()
f1.name = 'egon'
print(f1.name)
# print(f1.__dict__)
print(f1.__slots__)
-
_doc_类方法
-
class Foo:
'我是描述信息' # 这个信息不能被继承
pass
class Bar(Foo):
pass
print(Bar.__doc__)
- c1.__module__获取当前c1是哪个模块产生的
- c1.__class__查看c1是哪个模块的哪个类产生的
-
__del__函数又叫析构函数
- 与描述符__delete__不同,当对象在内存中释放时,自动触发执行,一般无需定义。只在实例被删除,或者程序执行完毕后运行
-
__call__方法
- 对象后边加括号,触发执行,呼叫不动。f1(),就是实例f1调用创建该实例的类的call方法
class Foo:
def __call__(self, *args, **kwargs):
print('实例执行了,obj()')
f1 = Foo()
f1() # 执行就是调用该实例的类的call方法
Foo() # 调用创建该Foo实例的类的call方法#类是对象,所以也是别的类产生的