类中定义的函数分为两大类
1、绑定方法
1.1、绑定到类的方法:用classmethod装饰器的方法
为类量身定制
类.bound_method(),自动将类当作第一个参数传入
(其实对象也可调用,但任然将类当作第一个参数传入)
class Foo: def __init__(self,name): self.name = name def tell(self): print(f"名字{self.name}") @classmethod # 把类本身当作第一个参数 def func(cls): # cls = Foo print(cls) f = Foo('LELE') Foo.func() 结果: <class '__main__.Foo'>
1.2、绑定到对象的方法:没有被任何装饰器装饰的方法
为对象量身定制
对象.bound\_method\(\),自动将对象当作第一个参数传入
(属于类的函数,类可以调用,但必须按照函数的规则来,没有自动传值那么一说)
class Foo: def __init__(self,name): self.name = name def tell(self): print(f"名字{self.name}") f = Foo('LELE') print(f.tell()) print(f.tell)
2、非绑定方法(不与类或者对象绑定):用staticmethod装饰器装饰的方法
不与类或对象绑定,类和对象都可以调用,但没有自动传值那么一说。就是一个普通工具而已
注意:与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,
而staticmethod装饰的方法,不管谁来调用,都没有自动传值一说
#=====非绑定方法----对象和类都可以用
class Foo:
def __init__(self,name):
self.name = name
def tell(self):# 绑定方法,绑定给对象
print(f"名字{self.name}")
@classmethod # 绑定方法:绑定给类 把类本身当作第一个参数
def func(cls): # cls = Foo
print(cls)
@staticmethod # 非绑定方法
def func2(x,y):
print(x+y)
f = Foo('LELE')
Foo.func2(1,2) # 类
f.func2(1,4)
类内部定义的函数:
绑定方法:绑定给对象 ,在内部创建的函数没有装饰器;绑定给类,有装饰器@classmethod把类本身当作第一个参数
非绑定方法:@staticmethod普通函数,谁都可调用
3、练习题
练习1:定义MySQL类 要求: 1.对象有id、host、port三个属性 2.定义工具create_id,在实例化时为每个对象随机生成id,保证id唯一 3.提供两种实例化方式,方式一:用户传入host和port 方式二:从配置文件中读取host和port进行实例化 4.为对象定制方法,save和get_obj_by_id,save能自动将对象序列化到文件中,文件路径为配置文件中DB_PATH,文件名为id号,保存之前验证对象是否已经存在,若存在则抛出异常,;get_obj_by_id方法用来从文件中反序列化出对象
import conf import hashlib,time,os,sys,pickle BASE_DIR = os.path.dirname(os.path.abspath(__file__)) sys.path.append(BASE_DIR) class MySQL: def __init__(self,host,port):#对象的初始化操作是自动完成的 self.host = host self.port = port self.id = MySQL.create_id() @staticmethod # 非绑定方法 def create_id(): #m = hashlib.md5() m = hashlib.md5(str(time.time()).encode('utf-8')) #m.update(bytes(str(m),encoding='utf-8')) return m.hexdigest() def tell(self): print(f"{self.id},{self.host},{self.port}") def save(self): id_filename = os.path.join(conf.DB_PATH,self.id+'.txt') #结合目录名和文件名 print(id_filename) with open(id_filename,'wb') as f: return pickle.dump(self,f) @classmethod # 绑定方法 MySQL(conf.host,conf.port) def get_obj_by_id(cls,filename): id_filename = os.path.join(conf.DB_PATH,filename+'.txt') with open(id_filename,'rb') as f: return pickle.load(f) @classmethod # 绑定方法 def id_from_conf(cls): #本题为类绑定 MySQL(conf.host,conf.port) return cls(conf.host,conf.port) # # 用户传入host和port user1 = MySQL('127.0.0.1',80) user1.tell() # # # save能自动将对象序列化到文件中 user1.save() # 从配置文件中读取host和port进行实例化 user2 = MySQL.id_from_conf() user2.tell() #get_obj_by_id方法用来从文件中反序列化出对象 user3 = MySQL.get_obj_by_id('d1f533ec8be01c54279e675188aa71e2') user3.tell()
配置文件conf.py代码:
import os,sys DB_PATH = os.path.dirname(os.path.abspath(__file__)) sys.path.append(DB_PATH) host = '127.0.1.2' port = 20
保存的时候生成文件:
悟已往之不谏,知来者之可追。