一、实现方法

class Function(object):
# 在类定义中定义变量
cls_variable = "class varibale" def __init__(self):
# 在构造函数中创建变量
self.__instance_variable = "instance variable" def instance_method(self):
print(self.cls_variable)
print(self.__instance_variable)
print("this is a instance method") @staticmethod
def static_method():
print(Function.cls_variable)
# print(Function.__instance_variable) 此处会报错,无法访问实例变量
print("this is a static method") @classmethod
def class_method(cls):
print(cls.cls_variable)
# print(cls.__instance_variable) 此处会报错,无法访问实例变量
print("this is a class method") @classmethod
def set_class_variable(cls):
cls.cls_variable = 'new class variable' def set_instace_varibale(self):
self.__instance_variable = 'new instance varibale' # 类实例可以调用类方法和静态方法
function1 = Function()
function1.set_class_variable()
function1.class_method()
function1.instance_method()
function1.static_method() function2 = Function()
function2.set_instace_varibale()
function2.class_method()
function2.instance_method()
function2.static_method()

1、从代码定义中,可以看到只是在默认传入参数的不同。

Function.class_method()
Function.static_method()
# 可以调用实例函数,只不过需要传入实例变量
Function.instance_method(function1)

2、从代码访问中,通过实例访问这三种方法是一样的。但是同时类访问时,不一样,实例函数需要传入实例。

3、函数访问变量中,有很大不同。

@classmethod
def class_method(cls):
print(cls.cls_variable)
# print(cls.__instance_variable) 此处会报错,无法访问实例变量

在init函数定义的是实例变量,因为变量前缀添加了self。在类开始时定义的类变量,不需要添加前缀。

在变量访问中,发现类函数和静态函数是无法直接访问实例变量的,因为在后续调用中,不知道是那个实例的。但是实例函数是可以访问类变量的。

4、修改变量的范围

new class variable
this is a class method
new class variable
instance variable
this is a instance method
new class variable
this is a static method

上图是function1中输出的结果。

new class variable
this is a class method
new class variable
new instance varibale
this is a instance method
new class variable
this is a static method
new class variable

这是function2的结果,则class variable都变化了。

如果通过类方法修改变量,则所有实例中的类变量都会修改,这个类似静态变量了

如果通过实例修改变量,只是修改对应的实例变量。

二、三者选择原则

通过第一节的分析,我们得知三者的不同,在访问权限和方式上,类方法和静态方法有很多相同之处。与实例方法的区别就是看看这个方法是不是实例独有的方法,或者需要访问实例变量的。另一个不同就是在继承上了。

1、类方法和静态方法

# -*- coding: utf-8 -*-
"""
@Time : 2017/12/29 9:50
@Author:dongbl
@Description:
""" class Function(object):
X = 1
Y = 2 @staticmethod
def averag(*mixes):
return sum(mixes) / len(mixes) @staticmethod
def static_method():
# 通过function调用,如果类名修改,此处需要修改不太方便
return Function.averag(Function.X, Function.Y) @classmethod
def class_method(cls):
return cls.averag(cls.X, cls.Y) class Subclass(Function):
X =3
Y = 5 @staticmethod
def averag(*mixes):
return sum(mixes) / 3 func = Subclass()
print(func.static_method())
print(func.class_method())

1、调用方式不同,另一方面就是如果类名修改,函数也修改

2、继承。这是两者最大的不同

1.5
2.6666666666666665

上面是两者的输出。

子类的实例继承了父类的static_method静态方法,调用该方法,还是调用的父类的方法和类属性。

子类的实例继承了父类的class_method类方法,调用该方法,调用的是子类的方法和子类的类属性。

这就是最大的不同,静态方法在类没有初始化,已经加载了,后续继承和她就没有关系了。同时静态方法关键明确指明了调用了Function的方法了,所以就无法修改了。这是本质。

三、类方法和实例方法

类中最常用的方法是实例方法, 即通过通过实例作为第一个参数的方法。

如果现在我们想写一些仅仅与类交互而不是和实例交互的方法会怎么样呢?在Python2.2以后可以使用@classmethod装饰器来创建类方法.

比如我们创建一个类:

class DateTest():
def __init__(self,year,month,day):
self.year = year
self.day = day
self.month = month def print_date(self):
print("{}:{}:{}".format(self.year,self.month,self.day))

如果用户输入的是“2017-12-02”这样的字符,我们在调用类之前就需要调整一下。

这个设计角度可以理解每个实例都可以调用这个转化函数。

# -*- coding: utf-8 -*-
"""
@Time : 2017/12/29 9:50
@Author:dongbl
@Description:
"""
class DateTest():
def __init__(self,year,month,day):
self.year = year
self.day = day
self.month = month def print_date(self):
print("{}:{}:{}".format(self.year,self.month,self.day)) @classmethod
def get_date(cls,string_date):
year,month,day = map(int,string_date.split('-'))
return cls(year,month,day) t = DateTest(2017,9,10)
r = DateTest.get_date("2017-12-09")
r.print_date()
t.print_date()

classmethod主要用途是作为构造函数。
Python只有一个构造函数__new__,如果想要多种构造函数就很不方便。只能在new里面写一堆if isinstance 。
有classmethod之后就可以用classmethod来写不同的构造函数,比如:
dict.fromkeys
fractions.Fraction.from_decimal
inspect.Signature.from_function
python里面大部分classmethod最后都是 return cls(XXX), return XXX.__new__ ()之类的

staticmethod主要用途是限定namespace,也就是说这个函数虽然是个普通的function,但是它只有这个class会用到,不适合作为module level的function。这时候就把它作为staticmethod。
如果不考虑namespace的问题的话直接在module里面def function就行了。

四、参考文献

1、python类的静态方法和类方法区别

2、知乎经典解答

python 类函数,实例函数,静态函数的更多相关文章

  1. 【引用】python 静态函数 类函数 实例函数

    1.关于定义类的一些奇特之处  今天在Python中定义一个类,很奇怪,不需要事先声明它的成员变量吗?暂时不知,先记录下来: class Account(object):    "一个简单的 ...

  2. python内置函数详细描述与实例演示

    python有许多内置函数,列出表格如下 内置函数 abs() delattr() hash() memoryview() set() all() dict() help() min() setatt ...

  3. python简单的函数定义和用法实例

    python简单的函数定义和用法实例 这篇文章主要介绍了python简单的函数定义和用法,实例分析了Python自定义函数及其使用方法,具有一定参考借鉴价值,需要的朋友可以参考下 具体分析如下: 这里 ...

  4. Python使用property函数定义的属性名与其他实例变量重名会怎么样?

    首先如果定义的属性名与该属性对应的操作方法操作的实例对象同名就会触发无穷的递归调用,相关部分请参考<Python案例详解:使用property函数定义与实例变量同名的属性会怎样?> 但如果 ...

  5. python中的函数

    Python 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也 ...

  6. python 内置函数和函数装饰器

    python内置函数 1.数学相关 abs(x) 取x绝对值 divmode(x,y) 取x除以y的商和余数,常用做分页,返回商和余数组成一个元组 pow(x,y[,z]) 取x的y次方 ,等同于x ...

  7. python之super()函数

    python之super()函数 python的构造器奇特, 使用魔方. 构造器内对基类对象的初始化同样也很奇特, 奇特到没有半点优雅! 在构造器中使用super(class, instance)返回 ...

  8. Python日期时间函数处理

    所有日期.时间的 api 都在datetime模块内. 1 日期的格式化输出 datetime => string import datetime now = datetime.datetime ...

  9. 由Python的super()函数想到的

    python-super *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !im ...

随机推荐

  1. Java中的Lock接口

    Synchronized & Lock synchronized 是Java语言中的关键字,由monitorenter,monitorexit两个指令实现.JVM会将monitorenter指 ...

  2. spring框架学习笔记3:使用注解代替配置文件

    1.导入context约束:spring-context-4.2.xsd 2.design模式打开xml配置文件,右键edit namespaces,点击add添加 完成后应该是这样: 配置文件中这样 ...

  3. 闲话ajax,例ajax轮询,ajax上传文件[开发篇]

    引语:ajax这门技术早已见怪不怪了,我本人也只是就自己真实的经验去总结一些不足道的话.供不是特别了解的朋友参考参考! 本来早就想写一篇关于ajax的文章的,但是前段时间一直很忙,就搁置了,趁着元旦放 ...

  4. Appium移动自动化测试入门及简单实例(python)

    1.介绍 Appium是一个移动端的自动化框架,可用于测试原生应用.移动网页应用和混合型应用,且是跨平台的.可用于IOS和Android以及firefox的操作系统.原生的应用是指用android或i ...

  5. Swift 里 Set(五)Adding & Removing Elements

    Adding Elements internal func _unsafeInsertNew(_ element: __owned Element) { _internalInvariant(coun ...

  6. Liferay7 BPM门户开发之9: 流程表单数据动态映射体系

    设计目的: 每个流程表单涉及不同的表单变量.比如请假流程有3个任务节点,分别是 Task1:开始流程,填写请假人.请假原因.请假开始时间.请假结束时间: Task2:上级审批,填写是否同意,审批意见: ...

  7. 【Redis面试题】Redis的字符串是怎么实现的?

    年前本人在找工作面试时在Redis相关问题上可栽了跟头.在面试前按常规套路准备了一下,比如 Redis 的常用5种数据结构,Redis持久化策略,Redis实现分布式锁,简单发布订阅等等都准备了,当时 ...

  8. ubuntu18.04 出现 Command 'ifconfig' not found 问题的解决办法

    我们在虚拟主机中查看ip地址需要输入ifconfig,但是报以下错误: 系统提示我们安装 net-tools,当我们输入以下命令,即可安装完成. sudo apt-get install net-to ...

  9. 在Android Studio添加本地aar包引用

    1.如何在Android Studio添加本地aar包引用 https://jingyan.baidu.com/article/2a13832890d08f074a134ff0.html 2.完成上述 ...

  10. odoo开发笔记 -- 后台日志输出及分析

    odoo开发笔记 -- 后台日志输出及分析 附:日志分析软件