反射和内置方法

我再也不想打气和每日金句了,我要吐了。

断点的使用

你用鼠标左键,去点代码的前面,也就是行数的后面,就会出现一个红点,大红点。

然后运行debug,程序运行到这一行的时候,就会卡主,然后你就可以点下一步下一步,一步一步看了。很好用,贼好用,炸 弹好用。

issubclass和isinstance的使用

这个也很简单。

issubclass的作用就是,判断一个类是不是另一个类的子类。具体用法如下

class Foo:
    pass
class Bar(Foo):
    pass

class Tt(Bar):
    pass
print(issubclass(Bar,Tt))
print(issubclass(Bar,Foo))
print(issubclass(Tt,object))

False
True
True

懂就好,别BB

isinstance的作用就是判断一个对象是不是一个类实例化出来的

#判断第一个参数是不是第二个参数的对象,返回true或者false
class Foo:
    pass
class Tt():
    pass

f=Foo()
print(isinstance(f,Foo))
print(isinstance(f,Tt))

True
False

反射

用户输入一段字符串,执行该字符串对应的方法

hasattr():判断一个属性是否在对象中,返回True或者False

getattr():通过字符串获取属性或方法,如果获取到了,就会返回相应的属性或方法

setattr():通过字符串来设置属性或方法# delattr():通过字符串来删除属性或方法

以上的方法都是以字符串为基础的,你通过各种途径得到一个变量,变量值是一个字符串,所以不能通过以往的方式来执行操作了。

hasattr()方法

class Foo:
    def run(self):
        print('run')
    def speak(self):
        print('speak')


p=Foo()
cmd='speak'
if hasattr(p,cmd):
    func=getattr(p,cmd)
    func()
else:
    print('该命令不存在')

speak

setattr()方法

#动态的往对象中放方法


class Foo:
    def run(self):
        print('run')
    def speak(self):
        print('speak')


p=Foo()
def test(a):
    print(a)
print(p.__dict__)
key='name'
value=test
setattr(p,key,value)
print(p.__dict__)
p.name('nick')

{}
{'name': <function test at 0x000001B1F02DF048>}
nick

delattr()方法

#动态的删除属性.
class Foo:
    def run(self):
        print('run')
    def speak(self):
        print('speak')
p=Foo()
p.name='lqz'
p.age=18
p.sex='male'
a=input('请输入要删除的属性:')
print(p.__dict__)
delattr(p,a)
print(p.__dict__)

请输入要删除的属性:age
{'name': 'lqz', 'age': 18, 'sex': 'male'}

内置方法

我们之前学过的__init__方法,他是我们在实例化对象的时候会自动调用的方法,今天来讲一下其他的几个内置方法,这些__开头并且__结束的方法都是内置方法,也叫作魔法方法,你可以在面试的时候讲一下魔法方法,指不定酒吧面试官给整蒙逼了。

__str__:如果不重写__str__ print打印会打印出内存地址,如果重写了,会打印出你想要的

__repr__ : 跟str类似,在交互式命令下直接写变量名,会执行__repr__

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

    def __str__(self):
        return '['+self.name+']'

f=Foo('nick')
print(f)

[nick]

当你使用了print,就会执行类里面的__str__方法,然后方法才返回,实际上你在打印的时候都是有调用这个方法的。当然,你如果去掉了这个方法,打印出来的就是这个对象的地址了。

setattr,delattr,getattr(重要)

这三个都是叫做点拦截方法

如果去对象中取属性,一旦取不到,会进入到__getattr__

如果去对象中赋值属性,一旦取不到,会进入到__setattr__

如果删除对象中的属性,会进入__delattr__

class Foo:
    def __init__(self,name):
        self.name=name
    def __getattr__(self, item):
        print('xxxx')
        return '你傻逼啊,没有这个字段'

    def __setattr__(self, key, value):
        print('yyyyy')

    def __delattr__(self, item):
        print('zzzzz')

f=Foo('nick')
print(f.age)
print(f.__dict__)

yyyyy
xxxx
你傻逼啊,没有这个字段
{}

我掐屌一算,你已经懵逼了,没错确实在调用不存在的属性的时候,才会调用getattr方法。那么既然这里调用到了,说明这个对象里面,一定没有name方法,那么为什么开始明明赋值了Nick,却没有呢?一开始赋值的时候,对象里面是没有name这个属性的,那么当你赋值不存在的属性的时候,就会调用setattr方法,这时候就只执行了这个方法,就结束了。并没有赋值。懂了吗?

然后打印f.age,age有吗,没有,所以走getattr方法。

delattr方法实例

class Foo:
    def __init__(self,name):
        self.name=name
    def __getattr__(self, item):
        print('xxxx')
        return '你傻逼啊,没有这个字段'

    # def __setattr__(self, key, value):
    #     print('yyyyy')

    def __delattr__(self, item):
        print('zzzzz')

f=Foo('nick')
print(f.__dict__)
del f.name
print(f.__dict__)

{'name': 'nick'}
zzzzz

相信这里细心的沙雕应该已经发现了我注释掉了setattr方法了,因为只要存在赋值情况,而且之前要是不存在这个属性,就一定会调用这个方法而且赋值这个操作就会失败了,所以我他妈没办法演示delattr这个方法!于是我只能把它注释了。

del操作的时候就会调用delattr方法,其实我们看到的删除,都是在这个方法里进行的。但是在这里我们只是打印了zzzzz,没有删除,所以dict里面还是有name这个属性的。

用非传统方法来取字典的值

class Mydict(dict):
    def __init__(self,**kwargs):
        #
        super().__init__(**kwargs)

    def __getattr__(self, item):
        #
        # print(item)
        return self[item]
    def __setattr__(self, key, value):
        self[key]=value

di=Mydict(name='lqz',age=18)
print(di['name'])
print(di.name)
di.sex='male'
print(di.sex)
di['sex']='male'
print(di.sex)

lqz
lqz
male
male

我们看到的是,Mydict继承了dict类,并且在实例化对象的时候自动调用了父类的init方法,这就生成了一个字典,然后我们通过di['name']和di.name的方式都可以取到name的值,因为在调用name的时候,发现没有,就回去执行getattr方法,然后你就懂得了。

#__item__系列  对象通过[] 中括号取值,赋值,删除值的时候,会调用
class Foo:
    def __init__(self, name):
        self.name = name
    def __getitem__(self, item):
        name=getattr(self,item)
        # print(name)
        # print(self.__dict__[item])
        return name
        # return self.__dict__[item]
    def __setitem__(self, key, value):
        print('obj[key]=lqz赋值时,执行我')
        self.__dict__[key] = value
    def __delitem__(self, key):
        print('del obj[key]时,执行我')
        self.__dict__.pop(key)
#
f=Foo('nick')
print(f['name'])

只要通过中括号来搞事情,那就会调用getitem或者setitem或者delitem。不多bb了。。

#__call__   对象加括号会调用它
class Foo:
    def __call__(self):
        print('xxxx')

f=Foo()
f()

懂?

#__enter__和__exit__
#上下文管理器,本质原来
# with open() as f:
#     pass

这个我不懂,明天再说

糟了,今天讲得太正经了。

posted @ 2019-09-02 22:32  chanyuli  阅读(157)  评论(0编辑  收藏  举报