python 面向对象进阶之对象内置方法

这是👉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

updatedupdated2019-11-202019-11-20