python @ @classmethod @staticmethod @property
发布日期:2021-11-21 04:41:25 浏览次数:41 分类:技术文章

本文共 4905 字,大约阅读时间需要 16 分钟。

转载自

http://www.cnblogs.com/elie/p/5876210.html

http://www.360doc.com/content/14/0811/11/16044571_400987060.shtml

1. 

Python中3种方式定义类方法, 常规方式, @classmethod修饰方式, @staticmethod修饰方式.

class A(object):    def foo(self, x):        print("executing foo(%s,%s)" % (self, x))        print('self:', self)    @classmethod    def class_foo(cls, x):        print("executing class_foo(%s,%s)" % (cls, x))        print('cls:', cls)    @staticmethod    def static_foo(x):        print("executing static_foo(%s)" % x)    a = A()

1.定义方式

普通的类方法foo()需要通过self参数隐式的传递当前类对象的实例。 @classmethod修饰的方法class_foo()需要通过cls参数传递当前类对象。@staticmethod修饰的方法定义与普通函数是一样的。

self和cls的区别不是强制的,只是PEP8中一种编程风格,slef通常用作实例方法的第一参数,cls通常用作类方法的第一参数。即通常用self来传递当前类对象的实例,cls传递当前类对象。

2.绑定对象

foo方法绑定对象A的实例,class_foo方法绑定对象A,static_foo没有参数绑定。
>>> print(a.foo)
>>>> print(a.class_foo)
>>>> print(a.static_foo)

3.调用方式

foo可通过实例a调用,类对像A直接调用会参数错误

>>> a.foo(1)executing foo(<__main__.A object at 0x0278B170>,1)self: <__main__.A object at 0x0278B170>>>> A.foo(1)Traceback (most recent call last):  File "
", line 1, in
TypeError: foo() missing 1 required positional argument: 'x'

但foo如下方式可以使用正常,显式的传递实例参数a

>>> A.foo(a, 1)executing foo(<__main__.A object at 0x0278B170>,1)self: <__main__.A object at 0x0278B170>

class_foo通过类对象或对象实例调用。

>>> A.class_foo(1)executing class_foo(
,1)cls:
>>> a.class_foo(1)executing class_foo(
,1)cls:

static_foo通过类对象或对象实例调用。

>>> A.static_foo(1)executing static_foo(1)>>> a.static_foo(1)executing static_foo(1)

4.继承与覆盖普通类函数是一样的。

class B(A):    passb = B()b.foo(1)b.class_foo(1)b.static_foo(1)# executing foo(<__main__.B object at 0x007027D0>,1)# self: <__main__.B object at 0x007027D0># executing class_foo(
,1)# cls:
# executing static_foo(1)

问题:@staticmethod修饰的方法函数与普通的类外函数,为什么不直接使用普通函数?

@staticmethod是把函数嵌入到类中的一种方式,函数就属于类,同时表明函数不需要访问这个类。通过子类的继承覆盖,能更好的组织代码。

 

 

 

2. python中的@符号

@就是python中的修饰器,装饰器(Decorators)是 Python 的一个重要部分。简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简短,也更Pythonic(Python范儿)。简而言之,修饰器封装一个函数,并且用这样或者那样的方式来修改它的行为,使得在这个函数运行之前或者之后执行某些动作。

详细解读见:

def minus(f):

    print 'minus'
    f()
def plus(f):
    print 'plus'
    f()
    
def test(a):
    if a > 3 :return plus
    else: return minus
@test(5)  
def xxx():
    print 'ok'
# 解释器 首先会解释    @符号后面的代码,如果和上面的代码类似,那么test(5)将会被执行,因为5>3,所以
#会返回一个函数指针plus, plus将下一行的函数指针xxx当作参数传入,直到执行完成。最后输出:
# plus ok

 

 

def minus(f):

    print 'minus'
    f()
@minus
def xxx():
    print 'ok'

# minus本身就已经是一个函数指针,所以会直接以xxx作为参数传入,结果会输出

# minus,ok

 

3. python中的属性修饰器  @property   

一个例子如下,下面是一个property class:

class Parrot:    def __init__(self):        self._voltage = 100000    @property    def voltage(self):        """Get the current voltage."""        return self._voltage

The @property decorator turns the voltage() method into a “getter” for a read-only attribute with the same name, and it sets the docstring for voltage to “Get the current voltage.” 也就是说这么做,就可以生成一个变量名为voltage,且值为100000的只读(read-only)属性(attribute)。若实例化一个 p = Parrot(), 则p.voltage=100000,不能改变,若需要改变,需要使用setter. 

转载自:https://www.cnblogs.com/Lambda721/p/6132206.html

考察 Student 类:

class Student(object):    def __init__(self, name, score):        self.name = name        self.score = score

当我们想要修改一个 Student 的 scroe 属性时,可以这么写:

s = Student('Bob', 59)s.score = 60

但是也可以这么写:

s.score = 1000

显然,直接给属性赋值无法检查分数的有效性。

如果利用两个方法:

class Student(object):    def __init__(self, name, score):        self.name = name        self.__score = score    def get_score(self):        return self.__score    def set_score(self, score):        if score < 0 or score > 100:            raise ValueError('invalid score')        self.__score = score

这样一来,s.set_score(1000) 就会报错。

这种使用 get/set 方法来封装对一个属性的访问在许多面向对象编程的语言中都很常见。

但是写 s.get_score() 和 s.set_score() 没有直接写 s.score 来得直接。

有没有两全其美的方法?----有。

因为Python支持高阶函数,可以用装饰器函数把 get/set 方法“装饰”成属性调用:

class Student(object):    def __init__(self, name, score):        self.name = name        self.__score = score    @property    def score(self):        return self.__score    @score.setter    def score(self, score):        if score < 0 or score > 100:            raise ValueError('invalid score')        self.__score = score

注意: 第一个score(self)是get方法,用@property装饰,第二个score(self, score)是set方法,用@score.setter装饰,@score.setter是前一个@property装饰后的副产品。

现在,就可以像使用属性一样设置score了:

>>> s = Student('Bob', 59)>>> s.score = 60>>> print s.score60>>> s.score = 1000Traceback (most recent call last):  ...ValueError: invalid score

说明对 score 赋值实际调用的是 set方法。

 

另一个例子  

 

注意到这个神奇的@property,我们在对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过getter和setter方法来实现的。

还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性。

下面的birth是可读写属性,而age就是一个只读属性,因为age可以根据birth和当前时间计算出来。

class Student(object):   @property  def birth(self):    return self._birth   @birth.setter  def birth(self, value):    self._birth = value   @property  def age(self):    return 2014 - self._birth

@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。

转载地址:https://blog.csdn.net/xiaojiajia007/article/details/71258103 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Install caffe on Ubuntu 14.04 with GTX 1080
下一篇:ubuntu 安装 matlab 2017a

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年04月13日 16时08分07秒