一、静态方法
1、定义
在方法名前加上@staticmethod装饰器,表示此方法为静态方法
class Dog(object): def __init__(self,name): self.name = name @staticmethod #在方法前加上staticmethod 装饰器定义静态方法 def eat(): print("the dog like eat bone")
2、静态方法特性
特性:只是名义上归类管理,实际上在静态方法里访问不了类或实例中的任何属性
(1)静态方法不可以传入self参数,如果想传调用时必须传入实例本身
class Dog(object): def __init__(self,name): self.name = name @staticmethod #在方法前加上staticmethod 装饰器定义静态方法 def eat(self,food): #可以定义,但是需传入实例本身 print("{0} like eat {1}".format(self.name,food)) d=Dog("Mike") d.eat(d,"bone")#传入实例d本身,否则会报错 # 结果 Mike like eat bone
(2)静态方法可以用类直接调用,直接调用时,不可以直接传入self,否则会报错
class Dog(object): def __init__(self,name): self.name = name @staticmethod #在方法前加上staticmethod 装饰器定义静态方法 def eat(food): print("Mike like eat {0}".format(food)) Dog.eat("bone") #结果 Mike like eat bone
(3)应用场景
一般情况下我们需要使用工具包的一些个类的封装,可以用静态方法,比如os模块
import os os.system() os.mkdir()
上面两个方法没有什么必然的联系在里面,所以可以这么用
二、类方法
1、定义
在方法名前加上@classmethod装饰器,表示此方法为类方法
class Dog(object): name="Mike" def __init__(self,name): self.name = name @classmethod #定义类方法 def eat(self,food): print("{0} like eat {0}".format(self.name,food))
2、类方法特性
特性:只能访问类变量(又叫静态属性),不能访问实例变量
(1)访问实例变量
class Dog(object): def __init__(self,name): self.name = name @classmethod #定义类方法 def eat(self,food): print("{0} like eat {1}".format(self.name,food)) d=Dog("Mike") d.eat("bone") #结果 Traceback (most recent call last): File "/Users/bianbian/PycharmProjects/test/ha.py", line 9, in <module> d.eat("bone") File "/Users/bianbian/PycharmProjects/test/ha.py", line 6, in eat print("{0} like eat {1}".format(self.name,food)) AttributeError: type object 'Dog' has no attribute 'name'
(2)访问类变量(又叫静态属性)
class Dog(object): name = "Coco" def __init__(self,name): self.name = name @classmethod #定义类方法 def eat(self,food): print("{0} like eat {1}".format(self.name,food)) d=Dog("Mike") d.eat("bone") #结果 Coco like eat bone
三、属性方法
1、定义
在方法名前加上@property装饰器,表示此方法为属性方法
class Dog(object): def __init__(self,name): self.name = name @property #定义属性方法 def eat(self): return self.name d = Dog("Mike") print(d.eat) #结果 Mike
2、特性
class Dog(object): def __init__(self,name): self.name = name @property #定义属性方法 def eat(self): print("{0} is eating".format(self.name)) d = Dog("Mike") d.eat #把方法变成静态属性调用 #结果 Mike is eating
如何传入参数??
(1)给转换后的静态属性赋值
用@静态方法名.setter去装饰方法,来给转换后的静态属性赋值
class Dog(object): def __init__(self,name): self.name = name @property #定义属性方法 def eat(self): print("{0} is eating {1}".format(self.name,"bone")) @eat.setter def eat(self,food): print("set food:",food) d = Dog("Mike") d.eat="hotdog" #给转成的静态变量赋值 d.eat #结果 set food: hotdog Mike is eating bone #并没有把设置的food传给eat
上述方法不可行
class Dog(object): def __init__(self,name): self.name = name self.__food = None @property #定义属性方法 def eat(self): print("{0} is eating {1}".format(self.name,self.__food)) @eat.setter def eat(self,food): print("set food:",food) self.__food = food d = Dog("Mike") d.eat #第一次赋值的是None d.eat = "hotdog" #给转成的静态变量赋值 d.eat #第二次赋值是hotdog #结果 Mike is eating None set food: hotdog Mike is eating hotdog
(2)删除转变的静态属性
用@静态方法名.deleter去装饰,表明可以删除转化后的静态属性
class Dog(object): def __init__(self,name): self.name = name self.__food = None @property #定义属性方法 def eat(self): print("{0} is eating {1}".format(self.name,self.__food)) @eat.setter def eat(self,food): print("set food:",food) self.__food = food @eat.deleter #定义可以删除eat这个静态属性 def eat(self): del self.__food print("food变量删除完毕") d = Dog("Mike") d.eat #第一次赋值的是None d.eat = "hotdog" #给转成的静态变量赋值 d.eat #第二次赋值是hotdog del d.eat #结果 Mike is eating None set food: hotdog Mike is eating hotdog food变量删除完毕
3、练习
想知道一个火车车次当前的状态,是到达了、晚点了、取消了、还是已经开走了,需要做下面几件事:
(1) 连接12306的API查询
(2)对查询结果进行解析
(3)返回结果给用户
火车的status属性的值是一系列动作后才得到的结果,所以每次调用时,其实都要经过一系列的动作才返回结果,但这些动作过程不需要用户关心, 用户只需要调用这个属性就可以
class Train(object): def __init__(self,name): self.train_name = name def checking_status(self): print("Checking the train is %s" %self.train_name) return 1 @property def train_status(self): status = self.checking_status() if status == 0: print("The train has canceled") elif status == 1: print("The train has arrived") elif status == 2: print("The train has drived away") else: print("Sorry,cannot confirm the train status,please check later") @train_status.setter def train_status(self,status): status_dic={ 0:"canceled", 1:"arrived", 2:"drived away" } print(" 33[31;1mHas changed the flight status to 33[0m",status_dic.get(status)) @train_status.deleter def train_status(self): print("The status has been removed") T = Train("D007") T.train_status T.train_status = 2 del T.train_status
结果
Checking the train is D007
The train has arrived
Has changed the flight status to drived away
The status has been removed
四、类的特殊成员方法
1、__doc__
表示类的描述信息
class Dog(object): """此类是形容Dog这个类""" # 类的描述信息 def __init__(self,name): self.name = name print(Dog.__doc__) #结果 此类是形容Dog这个类
2、__module__和__class__
__module__: 表示当前操作的对象在哪个模块
__class__:表示当前操作的对象的类是什么
cc.py里面的内容
class Dog(object): def __init__(self): self.name = "Mike"
21123.py里面的内容
from lib.cc import Dog obj = Dog() print(obj.__module__) #表示当前操作的对象在哪个模块 print(obj.__class__) #表示当前操作的对象的类是什么
运行21123.py,结果:
lib.cc <class 'lib.cc.Dog'>
3、__init__
构造方法,通过类创建对象时,自动触发执行
4、__del__
析构方法,当对象在内存中被释放时,自动触发执行
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,
所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的
5、__call__
对象后面加括号,触发执行
class Dog(object): def __init__(self): self.name = "Mike" def __call__(self, *args, **kwargs): #重写call方法 print("重写call方法",args,kwargs) D = Dog() #执行__init__ D(1,2,3,4,name="Coco") # 执行call方法,也可以写成 Dog()(1,2,3,4,name="Coco") #结果 重写call方法 (1, 2, 3, 4) {'name': 'Coco'}
构造方法的执行是由创建对象触发的,即:对象 = 类名() ;
而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
6、__dict__
查看类或对象中的所有成员
(1)类.__dict__
效果:打印类中所有的属性,不包括实例属性
class Dog(object): name = "Coco" def __init__(self,food): self.name = name self.food =food def food(self, *args, **kwargs): print("food",args,kwargs) print(Dog.__dict__) #结果 {'__module__': '__main__', 'name': 'Coco', '__init__': <function Dog.__init__ at 0x102ab5ea0>, 'food': <function Dog.food at 0x102ab5d90>, '__dict__': <attribute '__dict__' of 'Dog' objects>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>, '__doc__': None}
(2)实例名.__dict__
效果:打印该实例的所有属性,不包括类属性
class Dog(object): name = "Coco" def __init__(self,name,food): self.name = name self.food =food def food(self, *args, **kwargs): print("food",args,kwargs) d = Dog("Mike","Bone") print(d.__dict__) #结果 {'name': 'Mike', 'food': 'Bone'} #打印该实例的所有属性,不包括类属性
7、__str__
如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值
class Dog(object): name = "Coco" def __init__(self,name): self.name = name def __str__(self): return "obj:{0}".format(self.name) d = Dog("Mike") print(d) #结果 obj:Mike
8、 __getitem__、__setitem__、__delitem__
用于索引操作,如字典。以上分别表示获取、设置、删除数据
class Dog(object): def __getitem__(self,key): print('__gettem__:',key) def __setitem__(self, key,value): print('__settem__:',key) def __delitem__(self,key): print('__delitem__:',key) d = Dog() d["name"]="mike" #自动触发__setitem__方法 d["name"] #自动触发__getitem__方法 del d["name"] # 自动触发__delitem__方法 #结果 __settem__: name __gettem__: name __delitem__: name
__delitem__没有做真正的删除,只是触发这个方法,想要真正删除,只需要在__delitem__函数中添加删除功能即可
五、总结
- 静态方法访问不了类或实例中的任何属性,它已经脱离了类,一般会用在一些工具包中
- 类方法,只能访问类变量,不能访问实例变量
- 属性方法是把一个方法变成一个静态属性