python 类函数,实例函数,静态函数
一、实现方法
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就行了。
四、参考文献
2、知乎经典解答
python 类函数,实例函数,静态函数的更多相关文章
- 【引用】python 静态函数 类函数 实例函数
1.关于定义类的一些奇特之处 今天在Python中定义一个类,很奇怪,不需要事先声明它的成员变量吗?暂时不知,先记录下来: class Account(object): "一个简单的 ...
- python内置函数详细描述与实例演示
python有许多内置函数,列出表格如下 内置函数 abs() delattr() hash() memoryview() set() all() dict() help() min() setatt ...
- python简单的函数定义和用法实例
python简单的函数定义和用法实例 这篇文章主要介绍了python简单的函数定义和用法,实例分析了Python自定义函数及其使用方法,具有一定参考借鉴价值,需要的朋友可以参考下 具体分析如下: 这里 ...
- Python使用property函数定义的属性名与其他实例变量重名会怎么样?
首先如果定义的属性名与该属性对应的操作方法操作的实例对象同名就会触发无穷的递归调用,相关部分请参考<Python案例详解:使用property函数定义与实例变量同名的属性会怎样?> 但如果 ...
- python中的函数
Python 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也 ...
- python 内置函数和函数装饰器
python内置函数 1.数学相关 abs(x) 取x绝对值 divmode(x,y) 取x除以y的商和余数,常用做分页,返回商和余数组成一个元组 pow(x,y[,z]) 取x的y次方 ,等同于x ...
- python之super()函数
python之super()函数 python的构造器奇特, 使用魔方. 构造器内对基类对象的初始化同样也很奇特, 奇特到没有半点优雅! 在构造器中使用super(class, instance)返回 ...
- Python日期时间函数处理
所有日期.时间的 api 都在datetime模块内. 1 日期的格式化输出 datetime => string import datetime now = datetime.datetime ...
- 由Python的super()函数想到的
python-super *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !im ...
随机推荐
- 第十九节:Java基本数据类型,循环结构与分支循环
基本数据类型 Java中的基本数据类型,有8种,在Java中有四种类型,8种基本数据类型. 字节 boolean 布尔型为1/8 byte 字节类型为1 short 短整型为2 char 字符型为2 ...
- Android开发工程师文集-Fragment,适配器,轮播图,ScrollView,Gallery 图片浏览器,Android常用布局样式
Android开发工程师文集-Fragment,适配器,轮播图,ScrollView,Gallery 图片浏览器,Android常用布局样式 Fragment FragmentManager frag ...
- 多个git使用的 ssh key共存
ssh-keygen -t rsa -C "ljkj028@qq.com" 不要一直回车,指定密钥为 id_rsa_ljkj 默认为(id_rsa) 同理 创建其他密钥 打开ssh ...
- docker,docker-compose部署服务器
搭建服务器 docker 是一种容器技术,作用是用来快速部署服务,docker-compose 是用来做docker 的多容器控制. 简单的来说:docker-compose即为一种自动化部署服务. ...
- python中除法的几种类型
传统除法:直接后缀小数点,同样结果是和最大的小数点对齐 >>> 1/2 0 >>> 1.0/2 0.5 >>> 1/2.0 0.5 >> ...
- Spring Boot Tomcat配置详解
参数配置容器 server.xx开头的是所有servlet容器通用的配置,server.tomcat.xx开头的是tomcat特有的参数,其它类似. 所有参数绑定配置类:org.springframe ...
- Java线程池种类、区别和适用场景
newCachedThreadPool: 底层:返回ThreadPoolExecutor实例,corePoolSize为0:maximumPoolSize为Integer.MAX_VALUE:keep ...
- @pathvariable和@RequestParam的区别
@PathVariable 获取的是请求路径url中的值: (http://xxx.xxx.com/get_10.html,侧重于请求的URL路径里面的{xx}变量 ) //获取url中某部分的值 @ ...
- 带你入门 Docker
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何 ...
- (转)Linux 系统设置 : dmesg 命令详解
原文:https://blog.csdn.net/yexiangCSDN/article/details/80683246 https://www.cnblogs.com/duanxz/p/34770 ...