NJU1healer的个人博客分享 http://blog.sciencenet.cn/u/NJU1healer

博文

Python中@staticmethod、@classmethod、@property

已有 942 次阅读 2020-11-8 21:13 |个人分类:Python|系统分类:科研笔记

(1)@staticmethod

       staticmethod用于修饰类中的方法,使其可以在不创建类实例的情况下调用方法这样做的好处是执行效率比较高。(类比其实就是C++里面的静态方法)当然,也可以像一般的方法一样用实例调用该方法。

       该方法一般被称为静态方法。静态方法不可以引用类中的属性或方法,其参数列表也不需要约定的默认参数self。静态方法就是类对外部函数的封装,有助于优化代码结构和提高程序的可读性

代码举例:

class Time():

    def __init__(self,sec):

        self.sec = sec

    #声明一个静态方法

    @staticmethod

    def sec_minutes(s1,s2):

        #返回两个时间差

        return abs(s1-s2)

 

#分别使用类名调用和使用实例调用静态方法

print("----------------------不通过例化的方法调用----------")

print(Time.sec_minutes(10,5)) #类直接调用

#结果为5 5


t = Time(10) #先实例化类,即对象

print("----------------------通过例化方法调用----------")

print(t.sec_minutes(t.sec,5)) #通过对象进行调用

(2)@classmethod

       classmethod是用来指定一个类的方法为类方法,长的像下面这个样子:

class cc:
    @classmethod
    def f(cls, arg1, arg2, ...): ...

       cls通常用作类方法的第一参数  跟self有点类似( __init__里面的slef通常用作实例方法的第一参数)。即通常用self来传递当前类的实例--对象,cls传递当前类。

       self 和cls 没有特别的含义,作用只是把参数绑定到普通的函数上, 不一定非得是self 或cls,可以换成别的xxx。

       那么为什么会出现classmethod?

      1--classmethod设计的目的是什么呢?事实上与Python面向对象编程有关的,由于Python不支持多个的參数重载构造函数,比方在C++里,构造函数能够依据參数个数不一样。能够写多个构造函数。Python为了解决问题,採用classmethod修饰符的方式,这样定义出来的函数就能够在类对象实例化之前调用这些函数,就相当于多个构造函数,解决多个构造函数的代码写在类外面的问题;

      2---类最基本的作用是实例化出一个对象,但是有的时候再实例化之前,就需要先和类做一定的交互,这种交互可能会影响实际实例化的过程,所以必须放在调用构造函数之前。大概也可能是因为这个原因出现了classmethod;

      3---直接一点来说,我们知道对于一个普通的类,我们要使用其中的函数的话,需要对类进行实例化,而一个类中,某个函数前面加上了staticmethod或者classmethod的话,那么这个函数就可以不通过实例化直接调用,可以通过类名进行调用的;

      4---@classmethod 定义的类方法是可选构造函数中,我们定义了一个类方法,类方法的第一个参数(cls)指代的就是类本身。类方法会用这个类来创建并返回最终的实例。使用类方法的另一个好处就是在继承的时候,保证了子类使用可选构造函数构造出来的类是子类的实例而不是父类的实例。

代码举例1:

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 :"
        print self.year
        print "month :"
        print self.month
        print "day :"
        print self.day
 
t=Data_test(2016,8,1)
t.out_date()
输出:
year :
2016
month :
8
day :
1
 
符合期望。
  
如果用户输入的是 "2016-8-1" 这样的字符格式,那么就需要调用Date_test 类前做一下处理:
  
string_date='2016-8-1'
year,month,day=map(int,string_date.split('-'))
s=Data_test(year,month,day)
 
先把‘2016-8-1’ 分解成 year,month,day 三个变量,然后转成int,再调用Date_test(year,month,day)函数。 也很符合期望。
  
那我可不可以把这个字符串处理的函数放到 Date_test 类当中呢?
  
那么@classmethod 就开始出场了
  
class Data_test2(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
 
    @classmethod
    def get_date(cls,data_as_string):
        #这里第一个参数是cls, 表示调用当前的类名
        year,month,day=map(int,string_date.split('-'))
        date1=cls(year,month,day)
        #返回的是一个初始化后的类
        return date1
 
    def out_date(self):
        print "year :"
        print self.year
        print "month :"
        print self.month
        print "day :"
        print self.day
 
在Date_test类里面创建一个成员函数, 前面用了@classmethod装饰。 它的作用就是有点像静态类,比静态类不一样的就是它可以传进来一个当前类作为第一个参数。
  
那么如何调用呢?
  
r=Data_test2.get_date("2016-8-6")
r.out_date()
输出:
year :
2016
month :
8
day :
1
这样子等于先调用get_date()对字符串进行出来,然后才使用Data_test的构造函数初始化。 
这样的好处就是你以后重构类的时候不必要修改构造函数,只需要额外添加你要处理的函数,然后使用装饰符 @classmethod 就可以了。

代码举例2:

       类方法的一个主要用途就是定义多个构造器。它接受一个class 作为第一个参数(cls)。在继承时也能工作的很好:

(3)@property

       Python中访问对象的属性可以这么做:实例名.变量名!!@property是python的一种装饰器,是用来修饰方法的。

       作用:我们可以使用@property装饰器来创建只读属性,@property装饰器会将方法转换为相同名称的只读属性,可以与所定义的属性配合使用,这样可以防止属性被修改。

通俗理解:可以使用@property装饰器将方法伪装成  属性 的样式使用

@property 下方的函数只能是self参数 ,不能有其他的参数,property 常和私有属性相结合使用。

代码举例:

使用场景:1.修饰方法,是方法可以像属性一样访问。

class DataSet(object):

  @property

  def method_with_property(self): ##含有@property

      return 15

  def method_without_property(self): ##不含@property

      return 15


l = DataSet()

print(l.method_with_property) # 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。

print(l.method_without_property())  #没有加@property , 必须使用正常的调用方法的形式,即在后面加()

两个都输出为15。

使用场景:2.与所定义的属性配合使用,这样可以防止属性被修改。

       由于python进行属性的定义时,没办法设置私有属性,因此要通过@property的方法来进行设置。这样可以隐藏属性名,让用户进行使用的时候无法随意修改。

class DataSet(object):

    def __init__(self):

        self._images = 1

        self._labels = 2    #定义属性的名称

    @property

    def images(self):   #方法加入@property后,这个方法相当于一个属性,这个属性可以让用户进行使用,而且用户有没办法随意修改。

        return self._images 

    @property

    def labels(self):

        return self._labels


l = DataSet() #用户进行属性调用的时候,直接调用images即可,而不用知道属性名_images,因此用户无法更改属性,从而保护了类的属性。

print(l.images) # 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。

【参考】

https://blog.csdn.net/appleyuchi/article/details/104070718

https://www.cnblogs.com/baxianhua/p/10845620.html

https://www.cnblogs.com/taysem/p/12156375.html

https://zhuanlan.zhihu.com/p/64487092

点滴分享,福泽你我!Add oil!



http://wap.sciencenet.cn/blog-3428464-1257579.html

上一篇:Pytorch中torch.autograd.grad()函数用法示例
下一篇:Scipy randint 与 Numpy randint 的区别

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2021-7-29 04:39

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部