静态方法、类方法和属性方法


在 Python 中有三种常用的方法装饰器,可以使普通的类实例方法变成带有特殊功能的方法,分别是静态方法、类方法和属性方法。

静态方法 / Static Method


在 def 定义之前加上 @staticmethod 进行装饰,便可以使该方法成为静态方法,静态方法无法调用实例属性。静态方法可以通过实例或类进行调用。通常用于无需生成实例或无需共享实例属性的方法中,比如一些纯粹的数学公式计算等场合。

 class Foo():
@staticmethod
def foo(a, b):
print('This is a staticmethod, cal result: %d' % (a+b)) Foo.foo(1, 2)
Foo().foo(3, 4)

代码中定义了一个简单的 Foo 类,并通过添加静态方法装饰器定义了一个 foo 静态方法,该方法会显示出传入的两个参数的计算结果,由于整个方法中不需要用到实例或实例的属性,因此可以定义为一个静态方法。

This is a staticmethod, cal result: 3
This is a staticmethod, cal result: 7

从输出的结果看到,无论是使用类还是类实例,都可以对静态方法进行调用。

类方法 / Class Method


在 def 定义之前加上 @classmethod 进行装饰,使得该方法成为类方法,类方法同样无法调用实例属性, 但是可以调用类属性,类方法可以通过实例或类进行调用。同时,类方法还可以用于在类实例化之前对类进行一些处理。

 class Foo:
num = 1 @classmethod
def instance(cls):
cls.num = 7
cls = cls()
return cls def __init__(self):
self.foo = Foo.num def test(self):
print('This is a test') cls_1 = Foo()
print("foo is: %d, num is: %d" % (cls_1.foo, cls_1.num)) # Change num from 1 to 7 before __init__
cls_2 = Foo.instance()
print("foo is: %d, num is: %d" % (cls_2.foo, cls_2.num))
cls_2.test()

上面的代码中,定义了一个类方法,这个类方法会在调用的时候修改 Foo 类的 num 属性,随后在生成一个类实例(第 7 行,这步实际上完成了一个类的初始化)并返回。首先不调用类方法,直接生成一个类实例 cls_1,随后查看 cls_1 中的属性值,然后在利用类方法,通过 Foo 直接调用 instance 方法生成一个类实例 cls_2,并同样的查看类实例中的属性,最后调用 test 方法来测试这个类实例是否可以和正常生成的类实例一样调用实例方法。

foo is: 1, num is: 1
foo is: 7, num is: 7
This is a test

最后的输出结果可以看出,直接生成的类实例 cls_1 中的属性并没有被改变,而通过类实例方法生成的类实例 cls_2 中的属性则变化了,同时这个 cls_2 也同样能够调用普通的实例方法。也就是说类方法可以通过类进行直接调用而不需要先经过实例化,同时类方法传入的第一个参数 cls 即为当前的类。
Note: 这种类方法可以用在单例模式中,确保一个类无论实例化多少次都只有一个实例对象存在。

属性方法 / Property Method


在 def 定义之前加上 @property 进行装饰,使得该方法成为属性方法,属性方法可以在外部像调用属性一样直接进行调用,若需要实现对属性方法值的修改,则还需要定义由 @methodname.setter 装饰的同名方法,在这个方法内实现对属性方法返回值的修改。

 class Foo(object):

     def __init__(self):
self._foo = None @property
def foo(self):
return self._foo @foo.setter
def foo(self, value):
if isinstance(value, int):
self._foo = (value + 0.5) if __name__ == "__main__":
f = Foo()
print("foo is %s" % f.foo)
f.foo = 1
print("foo is %s" % f.foo)

上面的代码中定义了一个 foo 的属性方法和属性方法的 setter,这样就是的 foo 这个方法使用起来就如同是一个属性一般,可以直接通过实例进行调用(第17 / 19 行),而 @foo.setter 装饰器也赋予了 foo 属性方法赋值的能力,可以通过类似属性赋值的方式直接给 foo 传递一个参数(第 18 行),并且此时还可以对这个传入的参数进行一定的操作(如第 12 / 13 行)。

foo is None
foo is 1.5

最终输出的结果中可以看出,foo 虽然是一个方法,但是其使用的方式却完全类似于一个属性,这中属性方法所提供的功能在面向对象编程的时候十分有效,常常可以通过定义好属性方法来实现一系列对象的操作,使得一个实例更加接近真实对象的行为方式(上面的例子可能不算十分恰当,不过可以理解为一个识别器,只要传入的是数字,便修改自身的 _foo 属性为该值+0.5,而在外部则无需关心这一实现,只把 foo 当做是一个属性赋值即可)。

相关阅读


1. 装饰器

Python的程序结构[1] -> 方法/Method[1] -> 静态方法、类方法和属性方法的更多相关文章

  1. Python的程序结构[2] -> 类/Class[0] -> 类的特殊属性

    类的特殊属性 / Special Property of Class Python 中通过 class 进行类的定义,类可以实例化成实例并利用实例对方法进行调用. 类中还包含的一些共有的特殊属性. 特 ...

  2. Python 静态方法、类方法和属性方法

    Python 静态方法.类方法和属性方法 静态方法(staticmethod) staticmethod不与类或者对象绑定,类和实例对象都可以调用,没有自动传值效果,Python内置函数staticm ...

  3. Python面向对象静态方法,类方法,属性方法

    Python面向对象静态方法,类方法,属性方法 属性: 公有属性 (属于类,每个类一份) 普通属性 (属于对象,每个对象一份) 私有属性 (属于对象,跟普通属性相似,只是不能通过对象直接访问) 方法: ...

  4. 【面试必问】python实例方法、类方法@classmethod、静态方法@staticmethod和属性方法@property区别

    [面试必问]python实例方法.类方法@classmethod.静态方法@staticmethod和属性方法@property区别 1.#类方法@classmethod,只能访问类变量,不能访问实例 ...

  5. python中静态方法、类方法、属性方法区别

    在python中,静态方法.类方法.属性方法,刚接触对于它们之间的区别确实让人疑惑. 类方法(@classmethod) 是一个函数修饰符,表是该函数是一个类方法 类方法第一个参数是cls,而实例方法 ...

  6. Python笔记_第四篇_高阶编程_实例化方法、静态方法、类方法和属性方法概念的解析。

    1.先叙述静态方法: 我们知道Python调用类的方法的时候都要进行一个实例化的处理.在面向对象中,一把存在静态类,静态方法,动态类.动态方法等乱七八糟的这么一些叫法.其实这些东西看起来抽象,但是很好 ...

  7. Python的程序结构[1] -> 方法/Method[0] -> 类实例方法、私有方法和抽象方法

    类实例方法.私有方法和抽象方法 Python中最常用的就是类实例方法,类似于属性中的类实例属性,同时,也存在与私有属性类似方法,即私有方法,下面介绍这两种常见的方法,以及一种特殊意义的类实例方法 -- ...

  8. Python的程序结构[1] -> 方法/Method[2] -> 魔术方法 __init__ / __del__ / __new__

    魔术方法 / Magic Method 魔法方法就是可以给你的类增加魔力的特殊方法(实质应称为特殊方法,魔术方法在JavaScript中有所体现,对象具有不透明特性,而且无法在自定义对象中模拟这些行为 ...

  9. Python的程序结构[1] -> 方法/Method[3] -> 魔术方法 __getattr__ 与代理模式

    __getattr__ 方法 __getattr__ 方法当对象调用内部属性(包括方法等)且未找到对应属性的时候会调用的特殊方法.利用这一特性,可是对函数实现一个代理模式. __getattr__方法 ...

随机推荐

  1. Windows Server 2008 R2 集群(OpenService “RemoteRegistry” 失败)笔记

    OpenService “RemoteRegistry” 失败. 我在创建验证域控服务器[系统]类别中 看到错误日志 我在域控服务器去看,在 computers 里面 是有这台 计算机,但是为什么不行 ...

  2. Timer的schedule和scheduleAtFixedRate方法的区别解析

    在java中,Timer类主要用于定时性.周期性任务 的触发,这个类中有两个方法比较难理解,那就是schedule和scheduleAtFixedRate方法,在这里就用实例分析一下 (1)sched ...

  3. SecureCRT自动登录跳板机/堡垒机并连接目标机器

    公司登录目标服务器,需要先登录跳板机(堡垒机),然后再登录目标机器,一共需要4.5步. MAC或LINUX机器可以写.SH脚本,那WINDOWS有没有一键登陆的方法呢? 常用的SecureCRT工具就 ...

  4. NGUI-使用UILabel呈现图片和不同格式的文字

    1.可以使用BBCode标记 [b]Bold[/b]                      粗体[i]italic[/i]                         斜体[u]underli ...

  5. Python网络编程(子进程的创建与处理、简单群聊工具)

    前言: 昨天我们已经了解了多进程的原理以及它的实际使用 Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊.普通的函数调用,调用一次,返回一次, 但是fork()调用一次,返回两次 ...

  6. 源码分析(一) HashMap 源码分析|JDK8

    HashMap是一个普遍应用于各大JAVA平台的最最最常用的数据结构.<K,V>的存储形式使HashMap备受广大java程序员的喜欢.JDK8中HashMap发生了很大的变化,例如:之前 ...

  7. django QuerySet 的常用API

    为了加深对queryset对象api的了解,我们建立了以下示例模型: from django.db import models class Author(models.Model): "&q ...

  8. [转]Shell dev-null详解

    转自: https://blog.csdn.net/wenwenxiong/article/details/46882733 1,可以将/dev/null看作"黑洞". 它非常等价 ...

  9. Tomcat 顶层结构

    Tomcat中最顶层的容器叫Server,代表整个服务器,Server中包含至少一个Service,用于具体提供服务. Service主要包含两部分:Connector   和   Container ...

  10. Python函数参数中的冒号与箭头

    在一些Python的工程项目中,我们会看到函数参数中会有冒号,有的函数后面会跟着一个箭头,你可能会疑惑,这些都是什么东西? 其实函数参数中的冒号是参数的类型建议符,告诉程序员希望传入的实参的类型.函数 ...