一、实现方法

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. Vue 父组件ajax异步更新数据,子组件props获取不到

    转载 https://blog.csdn.net/d295968572/article/details/80810349 当父组件 axjos 获取数据,子组件使用 props 接收数据时,执行 mo ...

  2. 阿里开源项目arthas在docker环境初始化

    需求 我前一篇是在window环境下做的测试,实际情况现在的生成环境程序都部署在了docker环境下,此环境对arthas可能会缺失很多必要组件 目前的基础环境是在docker容器中,只存在基本的to ...

  3. 第五篇: 路由网关(zuul)

    在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统. 在Spring Cloud ...

  4. python(leetcode)-350两个数组的交集

    给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2,2] 示例 2: 输入: nums1 = [4,9,5 ...

  5. DevExpress GridView自动滚动

    引言 最新有一个winform项目使用的是DevExpress的控件,所以最近都在摸索使用这套控件,实在是佩服整套控件的强大,同时代码写起来也简洁.客户有一个需求,希望报表结果能在外接的大屏幕上定时滚 ...

  6. Appium+Python 自动化-appium常用元素定位方法

    https://www.cnblogs.com/rabbit-testing/p/8042733.html 大牛 https://blog.csdn.net/kaka1121/article/deta ...

  7. 微信小程序https配置

    先简单说下什么是https,https与http区别 ,以及https的原理 什么是https 在说HTTPS之前先说说什么是HTTP,HTTP就是我们平时浏览网页时候使用的一种协议.HTTP协议传输 ...

  8. ARP的通信过程

    在当今的以太网络通信中,在IP数据包中有两个必不可少的地址,那就是IP地址和网卡地址(即MAC地址),在数据包中,无论是IP地址还是MAC地址,都有源地址和目标地址,因为通信是双方的,所以就必须同时拥 ...

  9. [转]debian9 安装任意版本mysql

    Debian 9 - Install MySQL Server The steps below will show you how to install whichever version of My ...

  10. Spring之Bean的作用域与生命周期

    在前面博客中提到容器启动获得BeanDefinition对象中有一个scope 属性.该属性控制着bean对象的作用域.本章节介绍Bean的作用域及生命周期,了解bean是怎么来的又怎么没的. 一.B ...