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
posted @ 2018-01-22 16:17  吴威振  阅读(324)  评论(0编辑  收藏  举报