反射和内置方法
我再也不想打气和每日金句了,我要吐了。
断点的使用
你用鼠标左键,去点代码的前面,也就是行数的后面,就会出现一个红点,大红点。
然后运行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
这个我不懂,明天再说
糟了,今天讲得太正经了。