python中@classmethod,@staticmethod和@property方法

在python类当中,经常会遇到@classmethod和@staticmethod这两个装饰器,那么到底它们的区别和作用是啥子呢?具体来看下。

@classmethod :默认有一个cls参数,用类或对象都可以调用。

@staticmethod:静态方法,无默认参数,用类和对象都可以调用。

 

1.@staticmethod

我们看下代码:

class A:
    def f1(x):
        print(x)
        
A.f1(2)  # 2  类.函数

  创建一个类,通过类调用函数

class A:
    @staticmethod
    def f1(x):
        print(x)
        
A.f1(2)  # 2  类.静态方法
A().f1(2)  # 2 对象.静态方法  这种情况下是可以执行的,如果上述f1没有被staticmethod装饰那么就会报错!!!

  创建一个类,通过类调用函数。同时,因为该方法被staticmethod装饰器装饰了,那么通过对象.方法 也是可以调用的。

所以在类中,通过@staticmethod装饰的函数,可以直接被类调用,也可以被实例化后的对象调用!!!

同时,发现@staticmethod装饰的函数根本不需要传递self这个参数。因为被@staticmethod装饰的函数是直接绑定在类上而不是对象上

那么再看个示例:

#静态方法  只是名义上归类管理,实际上在静态方法里访问不了类或实例中 的任何属性
class Dog(object):
    def __init__(self,name):
        self.name=name
    @staticmethod #实际上跟类本身已没什么关系,只是名义上是类的方法(与类无关,不能访问类里的任何属性和方法)
    def eat(self,name):
        print("%s is eating %s"%(self.name,name))
        
d=Dog('sb')
# d.eat('baozi')#出错  原因是eat需要一个self参数,但调用时却没有传递,没错,因为当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了
#解决办法
#1.调用时主动传递实例本身给eat方法#在eat中去掉self参数,但这也意味着,在eat中不能通过self.调用实例中的其他变量了
d.eat(d,'baozi')
#执行结果
>>>sb is eating baozi

上述代码中,静态方法访问不了类或者实例中的任何属性。如果想要访问,则调用时主动传递实例本身。

2.@classmethod

class A:
    @classmethod
    def f1(cls,x):
        print(x)
        
A.f1(2)  # 2  类.方法
A().f1(2) # 2  对象.方法

  创建一个类,通过类调用函数。同时,因为该方法被classmethod装饰器装饰了,那么通过对象.方法 也是可以调用的。但注意,在被装饰方法中,必须传递cls参数!!!

class B:
    name = 'bruce'
    age = 16
    @classmethod
    def f1(cls,x):
        print(x)
        print(cls.age)
        print(cls.name)


B().f1(1) 
# 1
# 16
# bruce

  上述中,说明被classmethod装饰后的方法,通过cls参数,在该方法中,可以调用该类的变量。

class C:

    @classmethod
    def f1(cls,x):
        print(x)
        cls().f2()

    def f2(self):
        print('hello world')

C.f1(1) 或者 C().f1(1)
# 1
# hello world

  上述中,说明被classmethod装饰后的方法,通过cls参数,在该方法中,可以调用该类的其他方法。

所以在类中,通过@classmethod装饰的函数,首先在方法中必须传递第一个参数cls, 该函数可以被类直接调用,也可以被对象调用!!!

同时,因为传递了一个cls,所以可以调用类中的其他变量和方法。

再看下示例:

 

class Dog(object):
    name='SB' #类变量
    def __init__(self,name):
        self.name=name
    @classmethod #类方法只能访问类变量,不能访问实例变量
    def eat(self,name):
        print('%s is eating %s'%(self.name,name))
    def talk(self,something):
        print("%s is talking %s"%(self.name,something))

d=Dog('Lulu')
d.eat('Mantou')

#执行结果

SB is eating Mantou

 类方法只能访问类变量,不能访问实例变量。

 

3.@property

将类中的方法变成属性方法,对象调用时直接.方法,不用再加一个‘()’。

示例:

class Rect:
    def __init__(self,area):
        self.__area = area
    @property
    def area(self):
        return self.__area
rect = Rect(30)
#直接通过方法名来访问 area 方法
print("矩形的面积是:",rect.area) # 30

要想实现对area进行修改,可以通过@setter来实现

@area.setter
def area(self, value):
    self.__area = value
再次运行如下代码:

rect.area = 90
print("修改后的面积:",rect.area)  # 90

要实现对area进行删除,可以通过@deleter实现

@area.deleter
def area(self):
    self.__area = 0

print(rect.area) # 0

总之,关于@property:

 1. @property装饰器:修饰的函数,类内调用时函数不用带小括号——getter方法
 2. @setter 装饰器:函数名和变量名相同,可以直接修改属性——seter方法。

 

 

 

posted on 2022-10-14 09:58  一先生94  阅读(631)  评论(0编辑  收藏  举报

导航