这是👉python 面向对象进阶之对象内置方法👈的摘要
反射相关
常用的就是hasattr,getattr
class A():
def __init__(self):
pass
def func(self):
print("func")
a = A()
a.name = "123"
a.age = 123
print(getattr(a,"name"))
getattr(a, "func")()
print(hasattr(a, "ame"))
setattr,delattr,用于设置变量和删除变量,不常用
用于对象的一些内置方法:
str
调用对象,自动输出
class B:
def __str__(self):
return 'str : class B'
def __repr__(self):
return 'repr : class B'
b = B()
print('%s' % b)
print('%r' % b)
getitem, setitem, delitem
用于索引操作,如字典。以上分别表示获取、设置、删除数据
class C(object):
def __init__(self):
self.value = {}
self.name = 'test'
def __getitem__(self, item):
print '__getitem__', item
return self.value[item]
def __setitem__(self, key, value):
print '__setitem__', key, value
self.value[key] = value
def __delitem__(self, key):
print '__delitem__', key
del self.value[key]
def __len__(self):
return len(self.value)
print C.__doc__
c = C()
#print c
#result = c['k1']
c['k2'] = 5
c['k1'] = "Hello"
print c['k2']
print len(c)
call
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 call 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行 __init__
obj() # 执行 __call__
hash
外部哈希,依赖与内置__hash__方法
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))
__eq__方法
用与判断两个对象是否相等,因为 == 默认是比较内存地址
class A():
def __init__(self, name):
self.name = name
def __eq__(self, other):
if (self.__dict__ == other.__dict__):
return True
a = A("test")
b = A("test")
print(a == b)
set()对象去重,依赖于hash,eq方法
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))
__del__()
方法
创建对象后,python解释器默认调用__init__()
方法;
当删除一个对象时,python解释器也会默认调用一个方法,这个方法为__del__()
方法
import time
class Animal(object):
# 初始化方法
# 创建完对象后会自动被调用
def __init__(self, name):
print('__init__方法被调用')
self.__name = name
# 析构方法
# 当对象被删除时,会自动被调用
def __del__(self):
print("__del__方法被调用")
print("%s对象马上被干掉了..."%self.__name)
# 创建对象
dog = Animal("哈皮狗")
# 删除对象
del dog
cat = Animal("波斯猫")
cat2 = cat
cat3 = cat
print("---马上 删除cat对象")
del cat
print("---马上 删除cat2对象")
del cat2
print("---马上 删除cat3对象")
del cat3
print("程序2秒钟后结束")
time.sleep(2)
结果:
总结
- 当有1个变量保存了对象的引用时,此对象的引用计数就会加1
- 当使用del删除变量指向的对象时,如果对象的引用计数不会1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除
slots
现在我们终于明白了,动态语言与静态语言的不同
动态语言:可以在运行的过程中,修改代码
静态语言:编译时已经确定好代码,运行过程中不能修改
如果我们想要限制实例的属性怎么办?比如,只允许对Person实例添加name和age属性。
为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:
>>> class Person(object):
__slots__ = ("name", "age")
>>> P = Person()
>>> P.name = "老王"
>>> P.age = 20
>>> P.score = 100
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
AttributeError: Person instance has no attribute 'score'
>>>
注意:
使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
In [67]: class Test(Person): ...: pass ...:
In [68]: t = Test()
In [69]: t.score = 100