赞
踩
总结一下:
实例方法:可以获取类属性、构造函数定义的变量,属于 method 类型。只能通过实例化调用。
静态方法:不能获取类属性、构造函数定义的变量,属于 function 类型。两种调用方式:类.方法名 ,实例化调用。
类方法 :可以获取类属性,不能获取构造函数定义的变量,属于 method 类型。两种调用方式:类.方法名 ,实例化调用。
修改类变量的例子:
class Worker: raise_percent = 1 # 默认没有涨工资,比例为1 def __init__(self, name, salary): self.name = name self.salary = salary @classmethod # 加入此装饰器 def ch_raise_percent(cls, num): # 修改涨薪比例的函数 cls.raise_percent = num * cls.raise_percent # 传入一个数乘以之前的涨薪比例 ''' 这里要多解释一下,传入的是cls,这里cls代表类本身。要传入类本身才能够修改类本身的内容(如类变量), 由于传的是类本身,使用class的话会与class定义语句有冲突,因此使用classmethod要传入类的信息时, 将类本身以cls形式传入。 后面传入的num是在调用这个函数(即ch_raise_percent)时传入的参数,这个参数和创建类实例需要的 参数是没有关系的,因为调用这个函数仅仅是修改了类本身的信息。 ''' Worker.ch_raise_percent(1.3) # 这里在类外部调用classmethod装饰的函数,并传入一个num参数用于修改涨薪比例 print(Worker.raise_percent) # 使用类本身查看其类变量是否变化 # 执行结果为1.3,表示这里我们确实把Worker类的raise_percent类变量给修改了。
有人可能会想使用其它方式不能直接修改类变量吗,比如在类函数中传入self,然后调用类变量(即self.raise_percent)来进行修改,但是实际上你在类函数中调用后修改产生的是局部变量,整个类是获取不到你修改得到的局部变量的。当然还有可能你会想使用global或者nonlocal(如global self.raise_percent或者self.raise_percent)等方法使函数产生的结果变成非局部变量,这个我也试了,好像是不行的。
产生类实例的方法真的是非常好用啊,比如你的初始数据是一堆有规则的字符串,而这些字符串中包含着每个类实例所需的参数,那么你只需要添加一个classmethod装饰的函数,用这个函数帮你处理一下你的字符串,将这些字符串分成独立的项,再将这些项传递给类就可以产生类实例啦!
class Worker: def __init__(self, name, age, height, salary): self.name = name self.age = age self.height = height self.salary = salary @classmethod def str_handler(cls, string): name, age, height, salary = string.split('/') # 将传入的字符串以/分割产生列表,一一对应 return cls(name, age, height, salary) # 这里return返回的就是cls,也就是一个类实例,将Worker类类实例需要的 # 所有项都传入了cls,这就是一个完完整整的类实例啦 # 要注意return返回值可以被变量接收,接收后就成为类实例咯 A = 'Jack/20/1.75/1000' B = 'Mary/18/1.65/2000' # 两个需要处理的字符串 a = Worker.str_handler(A) b = Worker.str_handler(B) # 两次调用此类中的函数,产生两个类实例即a和b print(a.name, a.age, a.height, a.salary) print(b.name, b.age, b.height, b.salary) # 查看类实例是否创建成功
staticmethod也叫静态方法,实际上staticmethod装饰的函数的功能可能和类本身没什么太大的关系,因为staticmethod装饰的函数不能传入类实例或者类变量或者刚刚提到的cls。因此这个函数处理的功能只是额外的,比如帮你记录一下日期之类的功能。这样的功能可能在某些时候会用上,所以就把这样的函数也顺带包装在类中。看一个例子就明白啦:
class Worker: def __init__(self, name, age, height, salary): self.name = name self.age = age self.height = height self.salary = salary @classmethod def str_handler(cls, string): name, age, height, salary = string.split('/') return cls(name, age, height, salary) @staticmethod # 静态方法装饰器 def read_file(worker_file): f = open(worker_file,'r') lines = f.readlines() return lines # 这里的功能就是读取工作人员的记录文件,将每一行内容作为一个item # 记录到lines列表,最后将列表传出以供后续利用 # 有没有留意到,这个和类本身的功能是没有关系的,也就是实际上我们在类外部执行这个函数 # 或者单独执行这些代码也是一样的功能,只不过包装在类中更便于管理和使用而已 all_workers = Worker.read_file('2020_workers.txt') # 使用上面的静态方法读取一个文件,这里假设有这个“2020_workers.txt”文件,其中每行都是 # Jack/20/1.75/1000 这样的内容 for item in all_workers: worker = Worker.str_handlerhandler(item) # 通过for循环可以将文件中所有行都转为类实例 # 后面对类实例的操作就不写啦
静态方法的内容较简单,就不多写啦。
相对来说property装饰器的使用可能较复杂一点,property的翻译就是属性,因此其跟属性有关啦。而装饰器又是用来装饰函数的,那其实加property装饰器的功能就是将函数的返回值作为类的属性啦。什么意思呢,也就是说我们调用这个被装饰的函数不需要加括号去运行,而是直接像变量或者属性一样获取这个值。
看下例子吧:
class Worker:
def __init__(self, name, salary):
self.name = name
self.salary = salary
@property
def name_and_salary(self):
return self.name+'的工资是'+str(self.salary)
# 需要有返回值,返回值作为获取到的属性嘛
A = Worker('Jack',1000)
A.name_and_salary
# 注意这里不用加括号哦,像变量或者属性一样去调用就好了
现在应该理解property的作用了吧,当然property不止这点作用,使用property装饰后,被装饰的函数就成为了新的装饰器,新的装饰器常用的有三个,如上例中就是getter(默认的,即赋予类使用者获取某属性的能力)、setter(赋予类使用者在类外部给某类属性重新赋值的能力)和deleter(赋予类使用者在类外部删除某属性的能力)。看下例子就理解啦:
class Worker: def __init__(self, name, salary): self.name = name self.salary = salary @property # 先使用property装饰原函数,装饰之后就可以使用setter和deleter方法来进行装饰并有更多的功能了 # 这里默认已经有了getter的功能,也就是能够获取到这个属性的能力 def view_salary(self): return self.salary @view_salary.setter # setter装饰器能够使我们在类外部重新设置view_salary这个属性 # 而没有setter的话就会报错 AttributeError: can't set attribute def view_salary(self, new_salary): self.salary = new_salary return new_salary @view_salary.deleter # deleter装饰器的设置使我们可以在类外部使用del删除这个属性,但是这里我试了将self.salary # 设置为其它值也是可以的哦,这个值设置非空的话还是会有属性继续存在的哦。也就是在类外部使用 # del的功能取决于你自己在这里设置的操作 # 我这里是设置为空值了 def view_salary(self): self.salary = None A = Worker('J',1000) A.view_salary = 2000 # 这里在外部进行赋值,是使用的设置的setter方法哦,没有setter会报错的!! print("使用setter后的view_salary 值是:"A.view_salary) del A.view_salary # 尝试删除 print("使用del后J 的view_salary 的属性值是:"A.view_salary)
Python同时继承多个父类有两种方法
class Employee: def __init__(self,salary): self.salary=salary def work(self, *args, **kwargs): print('普通员工在写代码,工资为:',self.salary) class Customer: def __init__(self,favourite,address): self.favourite=favourite self.address=address def info (self): print('我是一个顾客,我的爱好是:%s,地址是%s'%(self.favourite,self.address)) class Mannager(Employee,Customer): def __init__(self,salary,favourite,address): print('Manngaer的构造方法') # 方法一:用未绑定方法来构造,使用类名直接构造,逐个调用 # Employee.__init__(self,salary) # Customer.__init__(self,favourite,address) # 方法二:使用super()和未绑定方法 super().__init__(salary) #与上一行代码效果相同 # super(Mannager,self).__init__(salary) Customer.__init__(self,favourite,address) m=Mannager(25000,'it产品','广州') m.work() m.info()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。