Python类装饰器@classmethod, @staticmethod, @property, since 2022-02-15

(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 "", line 1, in 
TypeError: 'str' object is not callable
>>> a.no_property()
'99g1aswell'
>>> a.no_property
>

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静态方法:实例中的静态方法调用的父类的方法和父类的属性。因静态方法传递的参数是原始类名(父类名)。
  • @propertyproperty方法:实例中的property方法调用的子类的属性。因property方法传递的参数是self,即子类对象。

你可能感兴趣的:(Python类装饰器@classmethod, @staticmethod, @property, since 2022-02-15)