python面向对象反射及内置方法

python面向对象反射及内置方法

一.isinstance与issubclass

isinstance:可以判断x是否是y类的实例化对象

issubclass:判断B类是否A类的子类

d={'a':1}
print(isinstance(d,dict))

class A:
    pass

class B(A):
    pass

print(issubclass(B,A))

二.反射

  1. hasattr(obj, str) 判断obj中是否包含str成员
  2. getattr(obj,str) 从obj中获取str成员。
  3. setattr(obj, str, value) 把obj中的str成员设置成value。这⾥的value可以是值,也可以是函数或者⽅法。
  4. delattr(obj, str) 把obj中的str成员删除掉。
class People:
    country = 'China'

    def __init__(self, name):
        self.name = name

    def eat(self):
        print("%s is eating" % self.name)
        return '你拿到我了'

peo1 = People('tom')

#操作函数属性
#1.判断有没有
print(hasattr(People,'eat'))
#2.查取出来
print(getattr(People,'eat')(peo1))
#3.增
def func():
    return 'hello'
setattr(People,'speak',func())
print(People.__dict__)
#4.删除
print(People.__dict__)
delattr(People,'eat')
print(People.__dict__)


#操作数据属性
print(hasattr(peo1, 'name'))  # peo1.name
print(hasattr(peo1, 'eat'))  # peo1.eat

print(getattr(peo1,'xxx',None))#找不到属性就返回None
res=getattr(peo1,'name')
print(res)

setattr(peo1,'age',18)
print(peo1.age)

delattr(peo1,'name')

三. 内置方法

  • __str__ :在对象被打印时自动触发,可以用来定义对象被打印时的输出信息,必须返回一个字符串的值.

​ 应该在方法内采集对象的相关的信息,然后根据需要拼成字符串的格式返回

  • __del__(析构方法):在对象被删除之前自动触发,可以用来做回收系统资源相关的事情.
__str__
class People:
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def __str__(self):

        return '<name:%s age:%s>'%(self.name,self.age)

obj=People('tom',18)
print(obj)


__del__

class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.f=open('a.txt','r',encoding='utf-8')


    def __del__(self):
        # print('run..........')
        # 做回收系统资源相关的事情
        self.f.close()

obj = People('tom', 18)
# print(obj)
# del obj

print('主')
  • __format__
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    __format_dict = {
        'n-a': '名字是:{obj.name}-年龄是:{obj.age}',  # 名字是:tom-年龄是:18
        'n:a': '名字是:{obj.name}:年龄是:{obj.age}',  # 名字是:tom:年龄是:18
        'n/a': '名字是:{obj.name}/年龄是:{obj.age}',  # 名字是:tom/年龄是:18
    }

    def __format__(self, format_spec):
        if not format_spec or format_spec not in self.__format_dict:
            format_spec = 'n-a'
        fmt = self.__format_dict[format_spec]
        print(fmt) #{obj.name}:{obj.age}
        return fmt.format(obj=self)

s1 = Student('tom', 24)
ret = format(s1, 'n/a')
print(ret)  # tom/24
  • __item__
class Foo:
    def __init__(self, name):
        self.name = name

    def __getitem__(self, item):
        print(self.__dict__[item])

    def __setitem__(self, key, value):
        print('obj[key]=tom赋值时,执行我')
        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')
print(f1.__dict__)
f1['age'] = 18
f1.hobby = '泡妞'
del f1.hobby
del f1['age']
f1['name'] = 'tom'
print(f1.__dict__)
  • __new__

其实__init__是在类实例被创建之后调用的,它完成的是类实例的初始化操作,而__new__方法正是创建这个类实例的方法

class Person:

    def __new__(cls, *args, **kwargs):
        print('调用__new__,创建类实例')
        return super().__new__(Person)

    def __init__(self, name, age):
        print('调用__init__,初始化实例')
        self.name = name
        self.age = age

    def __str__(self):
        return '<Person: {}({})>'.format(self.name, self.age)

p1 = Person('张三', 24)
print(p1)
调用__new__,创建类实例
调用__init__,初始化实例
<Person: 张三(24)>

__new__方法在类定义中不是必须写的,如果没定义的话默认会调用object.__new__去创建一个对象(因为创建类的时候默认继承的就是object)。

如果我们在类中定义了__new__方法,就是重写了默认的__new__方法,我们可以借此自定义创建对象的行为。

举个例子:

重写类的__new__方法来实现单例模式。

class Singleton:
    # 重写__new__方法,实现每一次实例化的时候,返回同一个instance对象
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            cls._instance = super().__new__(Singleton)
        return cls._instance

    def __init__(self, name, age):
        self.name = name
        self.age = age


s1 = Singleton('张三', 24)
s2 = Singleton('李四', 20)
print(s1, s2)  # 这两实例都一样
print(s1.name, s2.name)
  • __call__

__call__方法的执行是由对象后加括号触发的,即:对象()。拥有此方法的对象可以像函数一样被调用。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __call__(self, *args, **kwargs):
        print('调用对象的__call__方法')

a = Person('张三', 24)  # 类Person可调用
a()  # 对象a可以调用

__new__,__init__,__call__等方法都不是必须写的。

猜你喜欢

转载自blog.csdn.net/qq_42721964/article/details/86541287