python中至少有三种比较常见的方法类型,即实例方法,类方法、静态方法。它们是如何定义的呢?如何调用的呢?它们又有何区别和作用呢?且看下文。
首先,这三种方法都定义在类中。下面我先简单说一下怎么定义和调用的。(PS:实例对象的权限最大。)
实例方法
定义:第一个参数必须是实例对象,该参数名一般约定为“self”,通过它来传递实例的属性和方法(也可以传类的属性和方法);
调用:只能由实例对象调用。
类方法
定义:使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法);
调用:实例对象和类对象都可以调用。
静态方法
定义:使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法;
调用:实例对象和类对象都可以调用。
实例方法
简而言之,实例方法就是类的实例能够使用的方法。这里不做过多解释。
类方法
使用装饰器@classmethod。
原则上,类方法是将类本身作为对象进行操作的方法。假设有个方法,且这个方法在逻辑上采用类本身作为对象来调用更合理,那么这个方法就可以定义为类方法。另外,如果需要继承,也可以定义为类方法。
类方法可以由类调用,而且因为传入了参数cls,故也可以由实例来调用。
静态方法两者都能调用
总结成一张表就是:
譬如,我想定义一个关于时间操作的类,其中有一个获取当前时间的函数。
import time class TimeTest(object): def __init__(self, hour, minute, second): self.hour = hour self.minute = minute self.second = second @staticmethod def showTime(): return time.strftime("%H:%M:%S", time.localtime()) print(TimeTest.showTime()) t = TimeTest(2, 10, 10) nowTime = t.showTime() print(nowTime)
如上,使用了静态方法(函数),若要获得当前时间的字符串时,并不一定需要实例化对象,此时对于静态方法而言,所在类更像是一种名称空间。
其实,我们也可以在类外面写一个同样的函数来做这些事,但是这样做就打乱了逻辑关系,也会导致以后代码维护困难。
静态方法、类方法使用区别或者说使用场景
由于python类中只能有一个初始化方法,不能按照不同的情况初始化类。
# coding:utf-8 class Book(object): def __init__(self, title): self.title = title @classmethod def class_method_create(cls, title): book = cls(title=title) return book @staticmethod def static_method_create(title): book= Book(title) return book book1 = Book("use instance_method_create book instance") book2 = Book.class_method_create("use class_method_create book instance") book3 = Book.static_method_create("use static_method_create book instance") print(book1.title) print(book2.title) print(book3.title)
运行结果:
use instance_method_create book instance
use class_method_create book instance
use static_method_create book instance
特别说明,静态方法也可以实现上面功能,当静态方法每次都要写上类的名字,不方便。
类中静态方法方法调用静态方法和类方法调用静态方法例子。
下面的代码,静态方法调用另一个静态方法,如果改用类方法调用静态方法,可以让cls代替类,
让代码看起来精简一些。也防止类名修改了,不用在类定义中修改原来的类名。
# coding:utf-8 class Foo(object): X = 1 Y = 2 @staticmethod def averag(*mixes): return sum(mixes) / len(mixes) @staticmethod def static_method(): # 在静态方法中调用静态方法 print "在静态方法中调用静态方法" return Foo.averag(Foo.X, Foo.Y) @classmethod def class_method(cls): # 在类方法中使用静态方法 print "在类方法中使用静态方法" return cls.averag(cls.X, cls.Y) foo = Foo() print(foo.static_method()) print(foo.class_method())
运行结果:
在静态方法中调用静态方法
1
在类方法中使用静态方法
1
继承类中的区别
从下面代码可以看出,如果子类继承父类的方法,子类覆盖了父类的静态方法,
子类的实例继承了父类的static_method静态方法,调用该方法,还是调用的父类的方法和类属性。
子类的实例继承了父类的class_method类方法,调用该方法,调用的是子类的方法和子类的类属性。
# coding:utf-8 class Foo(object): X = 1 Y = 14 @staticmethod def averag(*mixes): # "父类中的静态方法" return sum(mixes) / len(mixes) @staticmethod def static_method(): # "父类中的静态方法" print "父类中的静态方法" return Foo.averag(Foo.X, Foo.Y) @classmethod def class_method(cls): # 父类中的类方法 print "父类中的类方法" return cls.averag(cls.X, cls.Y) class Son(Foo): X = 3 Y = 5 @staticmethod def averag(*mixes): # "子类中重载了父类的静态方法" print "子类中重载了父类的静态方法" print "666 ",mixes return sum(mixes) / 3 p = Son() print "result of p.averag(1,5)" print (p.averag(1,5)) print "result of p.static_method()" print(p.static_method()) print "result of p.class_method()" print(p.class_method())
结果如下:
result of p.averag(1,5)
子类中重载了父类的静态方法
666 (1, 5)
2
result of p.static_method()
父类中的静态方法
7
result of p.class_method()
父类中的类方法
子类中重载了父类的静态方法
666 (3, 5)
2
一、私有变量的定义
在Python中,有以下几种方式来定义变量:
- xx:公有变量
- _xx:单前置下划线,私有化属性或方法,类对象和子类可以访问,from somemodule import *禁止导入
- __xx:双前置下划线,私有化属性或方法,无法在外部直接访问(名字重整所以访问不到)
- __xx__:双前后下划线,系统定义名字(不要自己发明这样的名字)
- xx_:单后置下划线,用于避免与Python关键词的冲突
如以下例子所示,我在test类中定义了num,_num 和 __num三个属性,并创建了test的类对象t,对这三个属性进行访问,__num不能被访问到
class test(object): def __init__(self): self.num = 10 self._num = 20 self.__num = 30 t = test() print(t.num) # 10 print(t._num) # 20 # print(t.__num) # AttributeError: 'test' object has no attribute '__num'
可以使用命令dir查看t中的属性和方法,__num的名字已经被重整为“_test__num”了,可以使用t._test__num对__num进行访问
注:虽然私有变量可以通过_类名__变量名来访问,但强烈建议不要这样做
二、使用不同方法导入模块,模块中私有变量的使用区别
在使用不同方法导入模块后,是否能使用模块中的私有属性和方法,有以下两种情况
- 在使用 from somemodule import * 导入模块的情况下,不能导入或使用私有属性和方法
- 在使用 import somemodule 导入模块的情况下,能导入并使用私有属性和方法
https://blog.csdn.net/helloxiaozhe/article/details/79940321