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()
一、从代码定义中,能够看到只是在默认传入参数的不一样。python
Function.class_method() Function.static_method() # 能够调用实例函数,只不过须要传入实例变量 Function.instance_method(function1)
二、从代码访问中,经过实例访问这三种方法是同样的。可是同时类访问时,不同,实例函数须要传入实例。函数
三、函数访问变量中,有很大不一样。this
@classmethod def class_method(cls): print(cls.cls_variable) # print(cls.__instance_variable) 此处会报错,没法访问实例变量
在init函数定义的是实例变量,由于变量前缀添加了self。在类开始时定义的类变量,不须要添加前缀。spa
在变量访问中,发现类函数和静态函数是没法直接访问实例变量的,由于在后续调用中,不知道是那个实例的。可是实例函数是能够访问类变量的。设计
四、修改变量的范围code
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中输出的结果。orm
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都变化了。blog
若是经过类方法修改变量,则全部实例中的类变量都会修改,这个相似静态变量了继承
若是经过实例修改变量,只是修改对应的实例变量。ip
经过第一节的分析,咱们得知三者的不一样,在访问权限和方式上,类方法和静态方法有不少相同之处。与实例方法的区别就是看看这个方法是否是实例独有的方法,或者须要访问实例变量的。另外一个不一样就是在继承上了。
# -*- 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.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就好了。
二、知乎经典解答