首页 > 技术文章 > 反射,__setattr__,__getattr__,__delattr__

amiee-785563694 2017-04-24 15:16 原文

1.isinstance用法

isinstance(x,y):用于判断x是不是y类型的数据,返回布尔值

           判断x对象是不是由y这个类实例化的

a="egon"
class People:
    def walk(self):
        print("walking")

p=People()
isinstance(a,str)
res=isinstance(p,People)
print(res)

 

2.issubclass用法

issubclass(x,y):用于判断x是不是y的子类,返回布尔值

class Anmail:
    def __init__(self,an_type):
        self.name=an_type

    def walk(self):
        print("walking")

class People(Anmail):
    def __init__(self,name):
        self.name=name

print(issubclass(People,Anmail))

 

3反射(hasattr,setattr,getattr,delattr)用法

hasattr(x,“name”)判断x中是否含有字符串name属性或者方法

判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。
需要注意的是name要用括号括起来

x:可以是类,可以是对象

y:属性的变量名

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

    def walk(self):
        print("======>walking")

    def eat(self):
        print("======>eatting")

p=People("egon","20","")

print(hasattr(p,"name"))      #True
print(hasattr(p,"walk"))      #True

 

setattr(x,"name",value)把x对象中字符串name(属性)的值修改为value

给对象的属性赋值,若属性不存在,先创建再赋值。

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

    def walk(self):
        print("======>walking")

    def eat(self):
        print("======>eatting")

p=People("egon","20","")

print(setattr(p,"name","alex"))           #p.name=alex
print(setattr(p,"walk","zou"))            #{'sex': '男', 'name': 'alex', 'walk': 'zou', 'age': '20'}

 

getattr(x,"name",None)

获取到x中name的属性,如果name是数据属性则返回的是一个值,如果name是一个方法则返回一个内存name的内存地址

多加参数None表示,如果x中没有name属性,不会报错,会返回一个None值

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

    def walk(self):
        print("======>walking")

    def eat(self):
        print("======>eatting")

p=People("egon","20","")


print(getattr(p,"name"))             #egon
print(getattr(p,"walk"))             #<bound method People.walk of <__main__.People object at 0x000001FCE4FFFBA8>>
getattr(p,"walk")()                  #======>walking

 

delattr(x,"name")

删除x中name的数据属性,不能删name的方法

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

    def walk(self):
        print("======>walking")

    def eat(self):
        print("======>eatting")

p=People("egon","20","")

delattr(p,"name")
print(p.__dict__)           #{'sex': '男', 'age': '20'}

 

4__setattr__,__getattr__,__delattr__的用法

__setattr__

`__setattr__`函数是用来设置对象的属性,通过object中的__setattr__函数来设置属性:

class People:
    def __init__(self,name,age,sex):
        self.name=name             #走到self.name的时候就会先执行__setattr__,self.name表示self.__dict__[name]
        self.age=age
        self.sex=sex

    def __setattr__(self, key, value):
        if not isinstance(value,str):    #可实现在实例化的时候定制一套规则,必须是什么样的数据类型
            raise TypeError("参数必须是字符串")
        self.__dict__[key]=value   #往字典__dict__中加入属性key=value


    def walk(self):
        print("======>walking")

    def eat(self):
        print("======>eatting")

p=People("egon",20,"")          #报错
p=People("egon","20","")        #正常

 

__getattr__

从对象中读取某个属性时,首先需要从self.__dicts__中搜索该属性,再从__getattr__中查找,如果类中没有对象调用的属性时,就会执行__getatter__这个函数

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

    def __getattr__(self, item):  #如果类中没有对象调用的属性时,就会执行这个函数
        print("没有这个属性")

    def walk(self):
        print("======>walking")

    def eat(self):
        print("======>eatting")
p=People("egon","20","")
p.drink                        #没有这个属性

 

__delattr__

`__delattr__`函数式用来删除对象的属性:

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

    def __delattr__(self, item):      #找到self.__dict__[item],删除
        #self.__dict__.pop(item)
        del self.__dict__[item]


    def walk(self):
        print("======>walking")

    def eat(self):
        print("======>eatting")
p=People("egon","20","")
del p.name
print(p.__dict__)                   #{'sex': '男', 'age': '20'}

 

 

5 定制自己的数据类型:

1.继承的方式

#用继承的方式定制一个新list的方法
class List(list):
    def append(self, object):             #派生出自己新的append功能,可以添加一个验证追加元素的必须是字符串
        if not isinstance(object,str):
            raise TypeError("追加的必须是字符串")
        super().append(object)            #super()只能使用到该类的上一级

l=List([7,8,9])
l.append("s")                             #正常
# l.append(5)                             #报错
l.insert(0,4)                             #由于是继承的关系,可继续使用list的所有功能

 

2.授权的方式

#用授权的方式来自制一个日志的记录文件
"""
思路:日志文件必须包括日期,使用者全部记录到一个文件中
方法:先获取到文件的句柄,把句柄当做一个对象来操作
"""

import time

class Open:
    def __init__(self,name,mode="r",encoding="utf-8"):
        self.name=name
        self.mode=mode
        self.encoding=encoding
        self.x=open(name, mode=mode, encoding=encoding)

    def write(self,line):
        t=time.strftime("%Y-%m-%d %x")
        self.x.write("%s %s"%(t,line))
        self.x.flush()

    def __getattr__(self,item):
        print("zhao budao gongnege")
        if not hasattr(self.x,item):
            print("没有%s功能"%item)
        else:
            print(item)
            return getattr(self.x,item)

f=Open("log.log","w",encoding="utf_8")
f.write("22222222")

6 通过字符串导入模块

通过__import__导入(官方不推荐使用)

#输入time
m=input("请输入需要导入的模块:")
model=__import__(m)
print(model.time())

推荐使用

import importlib
t=importlib.import_module("time")
print(t.time())

7 练习

# 基于授权定制自己的列表类型,要求定制的自己的__init__方法,
class List:
    def __init__(self,*args):
        self.x=list(*args)

    def __str__(self):
        return str(self.x)
# 定制自己的append:只能向列表加入字符串类型的值
    def append(self, object):
        if not isinstance(object, str):
            raise TypeError("必须追加字符串类型的数据")
        return self.x.append(object)

# 定制显示列表中间那个值的属性(提示:property)
    @property
    def middle(self):
        n=int(len(self.x)/2)
        return self.x[n]

# 其余方法都使用list默认的(提示:__getattr__加反射)
    def __getattr__(self, item):
        if not hasattr(self.x,item):
            print("没有%s方法"%(item))
        else:
            return getattr(self.x,item)

l=List((1,2,4,5))
l.append("2")
print(l)
res=l.middle
print(res)

  

 

推荐阅读