Python课程回顾(day24)
绑定方法与非绑定方法
根据我们之前学过的继承与组合,我们已经知道了一种绑定方法:
绑定给对象的方法:在类中定义的函数没有被任何装饰器装饰的情况下,默认就是绑定给对象的,而类虽然也可以调用,但使用类调用函数的情况下,那么这个函数就只是一个普通的函数(需要按照规定传值)。
而今天我们所要学习的则是在类中如何将函数绑定给类呢?
关键字:classmethod,在要绑定的函数之上加入@classmethod装饰器,那么这个函数就是绑定给类的,对象也可以调用,不过依然默认传入的参数是类
需要强调的是,绑定方法的特殊之处就在于无论是对象还是类,绑定给谁就应该由谁来调用,而谁来调用则会将其作为第一个参数自动传入到函数内。
非绑定方法:关键字 staticmethod,在不需要进行任何绑定的函数上加入装饰器@staticmethod
非绑定方法基本等同于我们之前学过的初始函数,无论对于类还是对象,它都是一个普通的函数,无论谁调用都要按照规定传入参数,不会自动传值
class Foo: def func1(self): # 默认绑定给对象 print('obj.func1') @classmethod def func2(cls): # 函数参数内从cls是在定义装饰器之后自动产生了,表明的就是会自动将类传入 print('Foo.func2') @staticmethod def func3(x, y): print('normal func3', x, y) obj = Foo() obj.func1() # func1会将obj当做第一个参数传入 obj.func2() # 绑定给类的方法对象来调用依然会将类当做第一个参数传入 obj.func3(1, 2) # 无论对象还是类直接调用都要以普通函数的规则进行传值 Foo.func3(1, 2)
在了解了基本的原理之后,我们要知道,我们所学的每一种方法都不是让你拿在手里看的,都是要用的,那么在什么场景下才需要绑定给类,以及在什么情况下函数不需要任何绑定关系呢?
绑定给类的方法及非绑定方法的应用:
settings文件内容: IP = 10.10.10.1 PORT = 3306 import settings # 让类在进行实例化时通过配置文件读取配置信息来完成实例化 class MySQL: def __init__(self, IP, PORT): self.id = self.create_id() # 会自动查找类内的create_id函数将得到的值赋值给self.id self.IP = IP self.PORT = PORT def tell_info(self): print('%s:%s:%s' % (self.id, self.IP, self.PORT)) @classmethod # 若不加装饰器则会默认绑定给对象的 def from_conf(cls): # 默认传入的是类名,无论类名是否改变不会影响功能 return cls(settings.IP, settings.PORT) # 将读取配置信息定义成函数,避免每次产生新对象时的重复输入 @staticmethod def create_id(): import uuid return uuid.uuid4() obj = MySQL.from_conf() # 首先调用类内的配置信息功能将所产生对象需要的两个参数从文件中读取出来赋值给所产生的对象 obj.tell_info() # 此时的obj对象已经有了足够的参数
hasattr setattr getattr delattr的使用
class Foo: def __init__(self, name, age): self.name = name self.age = age # 这四个关键字都是通过字符串来对属性进行操作的 obj = Foo('klf', 18) print(hasattr(obj, 'name')) # 判断obj下是否有name这个属性,返回布尔值 setattr(obj, 'name', 'KLF') # 更改obj下name属性的值,若属性不存在则会为obj添加该属性 res = getattr(obj, 'name', '滚犊子') # 得到obj下name的属性值然后赋值给res,若name属性不存在则返回滚犊子 delattr(obj, 'age') # 删除obj下的age属性,若属性不存在则会报错
isinstance与issubclass
class Foo: pass obj = Foo() class Bar(Foo): pass print(isinstance(obj, Foo)) # 判断第一个参数是否是第二个参数的一个对象,我们在学习了一切皆对象之后知道了类型就是类,而且我们也可以自己定义类型,那么我们在以后就多无需使用type来进行判断了
print(issubclass(Bar, Foo)) # 判断第一个参数是否是第二个参数的一个子类
__str__方法
class Foo: def __init__(self, name, age): self.name = name self.age = age def __str__(self): res = '| 姓名:%-5s|\n| 年龄:%-5s|' % (self.name, self.age) return res # __str__方法会在print对象时自动触发函数体代码然后将拿到的返回值print出来 obj = Foo('klf', 19) print(obj) # 此时打印obj = 打印obj.__str__
#注意:
其实我们之前一直在用这种方法,比如我们的len,list
__del__方法
class Foo: def __init__(self, x, y, filename): self.x = x self.y = y self.f = open(filename, 'r', encoding='utf-8') def __del__(self): # 在代码执行完毕时会回收我们程序的内存资源,但不会回收操作系统资源, self.f.close() # 而文件就属于操作系统的内存资源,我们通过程序对操作系统进行操作打开文件, # 但程序运行完毕后回收的只是我们程序的资源,所以我们需要在程序执行完毕后主动关闭文件. # 而__Del__的主要作用就是在回收程序资源时触发执行,用于回收系统资源 obj = Foo(1, 2, 'a.txt')