Python的程序结构[1] -> 方法/Method[1] -> 静态方法、类方法和属性方法
静态方法、类方法和属性方法
在 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] -> 静态方法、类方法和属性方法的更多相关文章
- Python的程序结构[2] -> 类/Class[0] -> 类的特殊属性
类的特殊属性 / Special Property of Class Python 中通过 class 进行类的定义,类可以实例化成实例并利用实例对方法进行调用. 类中还包含的一些共有的特殊属性. 特 ...
- Python 静态方法、类方法和属性方法
Python 静态方法.类方法和属性方法 静态方法(staticmethod) staticmethod不与类或者对象绑定,类和实例对象都可以调用,没有自动传值效果,Python内置函数staticm ...
- Python面向对象静态方法,类方法,属性方法
Python面向对象静态方法,类方法,属性方法 属性: 公有属性 (属于类,每个类一份) 普通属性 (属于对象,每个对象一份) 私有属性 (属于对象,跟普通属性相似,只是不能通过对象直接访问) 方法: ...
- 【面试必问】python实例方法、类方法@classmethod、静态方法@staticmethod和属性方法@property区别
[面试必问]python实例方法.类方法@classmethod.静态方法@staticmethod和属性方法@property区别 1.#类方法@classmethod,只能访问类变量,不能访问实例 ...
- python中静态方法、类方法、属性方法区别
在python中,静态方法.类方法.属性方法,刚接触对于它们之间的区别确实让人疑惑. 类方法(@classmethod) 是一个函数修饰符,表是该函数是一个类方法 类方法第一个参数是cls,而实例方法 ...
- Python笔记_第四篇_高阶编程_实例化方法、静态方法、类方法和属性方法概念的解析。
1.先叙述静态方法: 我们知道Python调用类的方法的时候都要进行一个实例化的处理.在面向对象中,一把存在静态类,静态方法,动态类.动态方法等乱七八糟的这么一些叫法.其实这些东西看起来抽象,但是很好 ...
- Python的程序结构[1] -> 方法/Method[0] -> 类实例方法、私有方法和抽象方法
类实例方法.私有方法和抽象方法 Python中最常用的就是类实例方法,类似于属性中的类实例属性,同时,也存在与私有属性类似方法,即私有方法,下面介绍这两种常见的方法,以及一种特殊意义的类实例方法 -- ...
- Python的程序结构[1] -> 方法/Method[2] -> 魔术方法 __init__ / __del__ / __new__
魔术方法 / Magic Method 魔法方法就是可以给你的类增加魔力的特殊方法(实质应称为特殊方法,魔术方法在JavaScript中有所体现,对象具有不透明特性,而且无法在自定义对象中模拟这些行为 ...
- Python的程序结构[1] -> 方法/Method[3] -> 魔术方法 __getattr__ 与代理模式
__getattr__ 方法 __getattr__ 方法当对象调用内部属性(包括方法等)且未找到对应属性的时候会调用的特殊方法.利用这一特性,可是对函数实现一个代理模式. __getattr__方法 ...
随机推荐
- 新生 & 语不惊人死不休 —— 《无限恐怖》读后有感
开篇声明,我博客中“小心情”这一系列,全都是日记啊随笔啊什么乱七八糟的.如果一不小心点进来了,不妨直接关掉.我自己曾经写过一段时间的日记,常常翻看,毫无疑问我的文笔是很差的,而且心情也是瞬息万变的.因 ...
- Canvas 图形组合方式
/** * 图形组合 */ function initDemo5() { var canvas = document.getElementById("demo5"); if (!c ...
- CentOS vim中backspace不能用,出现^?的解决方法
查看在VI配置器下面使用backspace删除时提示输出那个字符例如:^H.^?.^a等字符如果输出的是:^? 字符 则使用以下命令:[oracle@junyii~]$ stty erase ^? 再 ...
- ImportError: dynamic module does not define module export function (PyInit__caffe)
使用python3运行caffe,报了该错误. 参考网址:https://stackoverflow.com/questions/34295136/importerror-dynamic-module ...
- 更换checkbox的原有样式
通常情况下,各个浏览器对的样式不一致,并且不那么美观.所以有时候设计需要我们更换原有的样式: html: <span><input type="checkbox" ...
- JavaWeb笔记(九)Ajax&Json
AJAX 实现方式 原生的JS实现方式 //1.创建核心对象 var xmlhttp; if (window.XMLHttpRequest) {// code for IE7+, Firefox, C ...
- 如何从List中删除元素
从List中删除元素,不能通过索引的方式遍历后删除,只能使用迭代器. 错误的实现 错误的实现方法 public class Demo { public static void main(Str ...
- CLion 的 Debug 模式是怎么回事
我对这个问题产生兴趣的起因是 Codeoforces Avito Challenges 2018 的 E 题,我想到了正解,但写得太慢,最后一刻才提交.有个地方写错,结果是 Runtime error ...
- 收藏一个JavaScript字符串连接方法
最近在看一同事写的代码时,有一个字符串用了一堆"+"号,看了半天没明天到底会输出什么样的内容,就想到用字符串连接的类,把以前的方法写成了类的方式,方便调用.下面的类支持实例调用和静 ...
- 《c程序设计语言》读书笔记-5.8-天数和日期转换错误检查
#include "stdio.h" #include "stdlib.h" #include "string.h" static char ...