(2022.02.15 Tues)
Python类自带了三个装饰器。被@classmethod
装饰的方法是类方法,被@staticmethod
装饰的方法是静态方法,没有装饰器的方法是实例方法。
@classmethod 类方法
该装饰器用于修饰类的方法中的类方法,该方法不因实例化而改变。
调用方式:
-
class_name.method_name
:在调用经@classmethod
修饰的类方法时不需要实例化类。 -
instance_name.method_name
:也可在实例化之后通过实例化的类名加方法名来调用。
类方法定义不需要指定self
作为输入参数,但第一个传递的参数必须是自身类的cls
,可用来调用类的方法,实例化对象等。可以返回一个类。定义格式如
class A:
@classmethod
def func(cls, args1, args2, ...):
pass
该装饰器的优势在于,当重构类的时候不需要修改构造函数,只需要添加新的方法,并用@classmethod
装饰即可。
# 初始类
class Data_test(object):
day=0
month=0
year=0
def __init__(self,year=0,month=0,day=0):
self.day=day
self.month=month
self.year=year
def out_date(self):
print("year : ", self.year, ", month: ", self.month, ", day: ", self.day)
# 新增
class Str2IntParam(Data_test):
@classmethod
def get_date(cls, string_date):
#这里第一个参数是cls, 表示调用当前的类名
year, month, day = map(int, string_date.split('-'))
date1 = cls(year, month, day)
#返回的是一个初始化后的类
return date1
$ r = Str2IntParam.get_date("2016-8-1")
$ r.out_date()
year: 2016, month: 8, day: 1
被@classmethod
修饰的类方法可修改类的状态,并应用于类的所有对象,比如可通过类方法修改类变量并应用于类的所有对象。It would modify the class state that would apply across all the instances of the class. For example, it can modify a class variable that would be applicable to all the instances.
(2022.02.21 Mon)
在下面这个例子中,类方法用于在每次类实例化时更新类变量cntr
。注意查看每次实例化之前和之后类变量的值。
class DemoClass:
cntr = 0
def __init__(self, name):
self.name = name
self.cntr = self.cntr_number()
@classmethod
def cntr_number(cls):
cls.cntr += 1
return cls.cntr
>>> DemoClass.cntr
0
>>> a = DemoClass(1)
>>> DemoClass.cntr
1
>>> b = DemoClass(2)
>>> DemoClass.cntr
2
>>> a.cntr
1
上面的演示说明类方法的使用使得类具有记忆力。这个特性可应用于深度学习的模型训练。
Python不支持类似于C++/Java中的方法重载(method overloading),于是使用@classmethod
修饰的类方法创建工厂方法(factory method)。在不同的案例中,工厂方式可以返回类对象,就像一个构造函数(constructor)。
@staticmethod 静态方法
(2022.02.16 Wed)
该指令修饰静态方法。静态方法的输入参数没有要求,不需要传入类方法的cls
作为输入参数,也不需要传入实例方法中的self
作为输入参数,传入参数可以任意指定。
调用方式:
class_name.method_name
-
instance_name.method_name
,在实例化后。
静态方法不改变类的行为和状态,静态方法不需要类本身作为一个输入参数,静态方法甚至可以放在类之外单独定义。在Python提出类的设计之前,通常在全局namespace中创建函数。类中加入静态方法很多时候是方便类的使用(?)使用静态方法甚至有时是糟糕设计的标志。
import time
class ClassA:
def __init__(self):
pass
@staticmethod
def show_time():
print(time.perf_time())
@property property方法
(2022.02.21 Mon)
@property
装饰器将方法转换为同名的属性,即调用该方法时不加扩号,将方法当成一个只读属性来调用。配合所定义的属性,可以防止对属性的修改。
class demoClass:
@property
def attr(self):
return '99g1'
def no_property(self):
return '99g1aswell'
实例化并调用的结果如下
>>> a.attr
'99g1'
>>> a.attr()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
>>> a.no_property()
'99g1aswell'
>>> a.no_property
<bound method demoClass.no_property of <__main__.demoClass object at 0x10f0de370>>
Python中无法设置私有属性,却可通过@property
来设置私有属性,隐藏属性名,使得用户无法修改。
class dataSet:
def __init__(self):
self._var1 = 1
self._var2 = 2
@property
def var1(self):
return self._var1
@property
def var2(self):
return self._var2
调用如下
>>> c = dataSet()
>>> c.var1
1
>>> c._var1
1
>>> c.var2
2
>>> c._var2
2
(2022.02.22 Tues)
下面通过一个例子演示类的继承过程中,子类对父类中不同方法的继承方式。
class allMethod:
x = 1
y = 2
@classmethod
def classm(cls):
return cls.x + cls.y
@staticmethod
def staticm():
return allMethod.x + allMethod.y
@property
def propertym(self):
return self.x
class testClass(allMethod):
x = 7
y = 5
实例化子类
>>> d = testClass()
>>> d.classm()
12
>>> d.staticm()
3
>>> d.propertym
7
对子类实例化之后,我们看到
-
@classmethod
类方法:实例中的类方法调用的是子类的方法和子类的属性。因类方法传递的参数是cls
,即子类本身。 -
@staticmethod
静态方法:实例中的静态方法调用的父类的方法和父类的属性。因静态方法传递的参数是原始类名(父类名)。 -
@property
property方法:实例中的property方法调用的子类的属性。因property方法传递的参数是self
,即子类对象。