Python Day 23(内置方法:反射,isinstance和issubclass,__str__和__repr__和其他双下方法)

Python Day 23(内置方法:反射,isinstance和issubclass,__str__和__repr__和其他双下方法)

反射

  python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

  使用字符串数据类型的变量名来操作一个变量的值,使用反射获取某个命名空间中的值.需要有一个变量指向这个命名空间的字符串数据类型的名字,再使用getattr获取值,如果是变量能直接获得结果,如果是函数,只能拿到内存地址,加上括号就是执行

反射的几种用法

使用类名反射   : 静态属性、类方法、静态方法
使用对象名反射 :对象属性、类中的普通方法
使用模块名反射 : 变量 函数 类
在自己所在的文件中反射全局变量 :getattr(sys.modules[__name__],'要反射的名字')

  hasattr

    判断是否存在,返回True,False (检测是否含有某属性)

class A:
    Name1 = 'alex'
    Name2 = 'egon'
    Name3 = 'guangtou'
    def __init__(self,name):
        self.name = name
    def func(self):
        print('in func',self.name )

if hasattr(A,'Name1'):   #类名 静态属性名(字符串类型)
    print(getattr(A,'Name1'))  #类名 静态属性名(字符串类型)
hasattr

  getattr

    获取属性

class A:
    Name1 = 'alex'
    Name2 = 'egon'
    Name3 = 'guangtou'
    def __init__(self,name):
        self.name = name
    def func(self):
        print('in func',self.name )

if hasattr(A,'Name1'):   #类名 静态属性名(字符串类型)
    print(getattr(A,'Name1'))  #类名 静态属性名(字符串类型)
getattr

  setattr

        添加和修改属性  

class A:
    Name1 = 'alex'
    Name2 = 'egon'
    Name3 = 'guangtou'
    def __init__(self,name):
        self.name = name
    def func(self):
        print('in func',self.name )

if hasattr(A,'Name1'):
    print(getattr(A,'Name1'))

print(A.__dict__)
A.Country = '中国' #增加
print(A.__dict__)
A.Country = '印度' #修改
print(A.__dict__)
setattr(A,'Country','日本')
print(A.__dict__)
setattr(A,'Country','德国')
print(A.__dict__)
setattr

  delattr

    删除属性 

class A:
    Name1 = 'alex'
    Name2 = 'egon'
    Name3 = 'guangtou'
    def __init__(self,name):
        self.name = name
    def func(self):
        print('in func',self.name )

if hasattr(A,'Name1'):
    print(getattr(A,'Name1'))

print(A.__dict__)
delattr(A,'Name1')
print(A.__dict__)
delattr

isinstance和issubclass

  isinstance

    判断对象和类的关系

a = 10
print(isinstance(a,int))  #判断对象类型

class F:pass
class Foo(F):pass

obj = Foo()
print(isinstance(obj,Foo)) #对象属于Foo类  True
print(isinstance(obj,F)) #可以判断继承关系  True
print(type(obj) is Foo) #对象属于Foo类  True
print(type(obj) is F) #无法判断继承类 False
isinstance

  issubclass

    判断是子类

class F:pass
class Foo(F):pass
print(issubclass(Foo,F))
print(issubclass(F,Foo))
issubclass

__str__和__repr__

  改变对象的字符串显示 必须返回一个str数据类型

  __str__     %s  str()   

  __repr__  %r  repr()

       当__str__存在时  %s 使用__str__方法,__repr__存在时  %s 使用__repr__方法,

  当__str__不存在时  %s 使用__repr__方法,__repr__存在时  %s 使用__repr__方法,

class B:
    def __str__(self):
        return 'str : class B'

    def __repr__(self):
        return 'repr : class B'
b = B()

print('%s' % b)
print('%r' % b)

==================
str : class B   #
repr : class B  #


*******************************
*******************************
class B:
#     def __str__(self):
#         return 'str : class B'

    def __repr__(self):
        return 'repr : class B'
b = B()
print('%s' % b)
print('%r' % b)
==================
repr : class B
repr : class B
View Code
str函数或者print函数--->obj.__str__()
repr或者交互式解释器--->obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__来代替输出
注意:这俩方法的返回值必须是字符串,否则抛出异常
__str__ __repr__ 注意事项

  __format__   format()

format_dict={
    'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
    'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
    'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
}
class School:
    def __init__(self,name,addr,type):
        self.name=name
        self.addr=addr
        self.type=type

    def __format__(self, format_spec):  # format_spec = 'nat'
        if not format_spec or format_spec not in format_dict:
            format_spec='nat'
        fmt=format_dict[format_spec]    # fmt = '{obj.name}-{obj.addr}-{obj.type}'
        return fmt.format(obj=self)

s1=School('oldboy1','北京','私立')
print(format(s1,'nat'))
print(format(s1,'tna'))
print(format(s1,'tan'))
print(format(s1,'asfdasdffd'))
__format__

其他双下方法

  __call__

    对象加上(),可以触发这个类的__call__方法。

class Foo:
    def __call__(self):
        print('call')

Foo()() #触发类的__call__方法

obj = Foo()
obj()  # 相当于调用__call__

=====================
call
call
__call__

  __len__

    内置函数的len函数是依赖类中的__len__

class Classes:
    def __init__(self,student_lst):
        self.student_lst = student_lst
    def __len__(self):return len(self.student_lst)

clas = Classes(['张三','程咬金','程咬银','程咬铁','程咬钢'])  #创建一个对象
print(len(clas.student_lst))
print(len(clas))
__len__
class Wahaha:
    def __init__(self,num,name,age):
        self.num = num
        self.name = name
        self.age = age
    def __len__(self):
        return len(self.__dict__) # 某个类中有多少个属性???
obj = Wahaha(6,'haha',7)
print(len(obj.__dict__))
print(len(obj))
View Code

  __hash__ 和 __eq__

  __hash__ 

     hash值计算

  __eq__

    比较是否值相同

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

    def __eq__(self, other):
        if type(self) == type(other) and \  #设置条件
            self.name == other.name and \
            self.sex == other.sex :
            return True
        else: return  False

p1 = Person('egon',40,'male')
p2 = Person('egon',50,'male')
p3 = Person('光头',80,'male')
print(p1==p2)  #直接比较对象
print(p1==p3)
__eq__
# 两个对象 的name 和 sex相同,那么这两个对象就是相同的对象
# 对100个对象进行去重
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 type(self) == type(other) and \
            self.name == other.name and \
            self.sex == other.sex :
            return True
        else: return  False
person_lst = [Person('egon',i,'male') for i in range(100)]
print(set(person_lst))  # hash是否相等,值是否相等  __hash__值相等,__eq__值也相等
print(hash(person_lst[1]))
print(hash(person_lst[2]))
# 根据每一个对象的hash值
__hash__ __eq__

猜你喜欢

转载自www.cnblogs.com/eailoo/p/9112993.html