版权声明:本文为博主原创文章,转载请注明作者和出处。https://blog.csdn.net/xq920831/article/details/82682821
开始今天的学习。
今天学习一些面向对象的进阶内容:
1. 静态方法和类方法
# -*- coding:utf-8 -*-
# Author: Agent Xu
class People(object):
name = "agentsun"
def __init__(self,name):
self.name = name
def eat(self,food):
print("%s is eating %s" %(self.name,food))
@staticmethod #实际上和类已经没有关系了,cook当做是一个单独的函数,所以不能用参数
def cook(self):
print("%s is cooking %s" %(self.name,"牛排"))
@classmethod #类方法,只能用类里定义的变量
def meet(self):
print("%s is in a meeting" %(self.name))
a = People("agentxu")
a.eat("西瓜") #agentxu is eating 西瓜
a.cook(a) #agentxu is cooking 牛排
a.meet() #agentsun is in a meeting
总结:
静态方法——只是名义上归类管理,实际上在静态方法里访问不了类或实例中的任何属性。
类方法——只能访问类变量,不能访问实例变量。
据说实际中用处不多。。。。
2. 属性方法
把一个方法变成静态属性。
class Animal(object):
def __init__(self,name):
self.name = name
@property
def hunt(self):
print("hunt the animal %s" %(self.name))
d = Animal("犀牛")
d.hunt #hunt the animal 犀牛
但是这样有一个很大的问题,不能传参数了。。。。。那怎么办呢
解决方法:再写一个同名的函数
class Animal(object):
def __init__(self,name):
self.name = name
@property
def hunt(self):
print("hunt the animal %s" %(self.name))
@hunt.setter
def hunt(self,people):
print("%s hunt the animal %s" %(people,self.name))
d = Animal("犀牛")
d.hunt #hunt the animal 犀牛
d.hunt = "agentxu" #agentxu hunt the animal 犀牛
d.hunt #hunt the animal 犀牛
#如果想保存参数的值则应改成下面的模式
class Animal1(object):
def __init__(self,name):
self.name = name
self.people = None
@property
def hunt1(self):
print("%s hunt the animal %s" %(self.people,self.name))
@hunt1.setter
def hunt1(self,people):
print("%s hunt the animal %s" %(people,self.name))
self.people = people
f = Animal1("犀牛")
f.hunt1 #None hunt the animal 犀牛
f.hunt1 = "agentxu" #agentxu hunt the animal 犀牛
f.hunt1 #agentxu hunt the animal 犀牛
如果想删除参数,加一个模块
@hunt1.deleter
def hunt1(self):
del self.people
print("删除完毕")
更多详细的例子参考:https://www.cnblogs.com/alex3714/articles/5213184.html
3. 特殊方法
- __doc__
class Dog(object):
'''这个类是用来描述一种动物的'''
def __init__(self,name):
self.name = name
#打印类的描述信息
print(Dog.__doc__) #这个类是用来描述一种动物的
-
__module__ 和 __class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
from day8.lizi import Animal
obj = Animal()
print(obj.__module__) #day8.lizi 输出属于哪个模块
print(obj.__class__) #<class 'day8.lizi.Animal'> 输出属于哪个类
-
__init__
构造方法,通过类创建对象时,自动触发执行。
-
__del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的
- __call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Dog(object):
'''这个类是用来描述一种动物的'''
def __init__(self,name):
self.name = name
def __call__(self, *args, **kwargs):
print("calling func")
e = Dog("dog")
Dog("dog")() #calling func
e() #calling func
或者带参数的也阔以。。。
class Dog(object):
'''这个类是用来描述一种动物的'''
def __init__(self,name):
self.name = name
def __call__(self, *args, **kwargs):
print("calling func ",args,kwargs)
e = Dog("dog")
e(1,2,3,name=666) #calling func (1, 2, 3) {'name': 666}
- __dict__
查看类或对象中的所有成员。
class Dog(object):
'''这个类是用来描述一种动物的'''
def __init__(self,name):
self.name = name
def __call__(self, *args, **kwargs):
print("calling func ",args,kwargs)
print(Dog.__dict__) #打印类里的所有属性,不包括实例属性
#{'__doc__': '这个类是用来描述一种动物的', '__dict__': <attribute '__dict__' of 'Dog' objects>, '__init__':
#<function Dog.__init__ at 0x0000000000BDF2F0>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>,
#'__call__': <function Dog.__call__ at 0x0000000000BDF378>, '__module__': '__main__'}
e = Dog("dog")
print(e.__dict__)
#{'name': 'dog'} 打印实例里的所有属性,不包括类属性
- __str__
如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
class
Foo:
def
__str__(
self
):
return
'alex li'
obj
=
Foo()
print
obj
# 输出:alex li
-
__getitem__、__setitem__、__delitem__
用于索引操作,如字典。以上分别表示获取、设置、删除数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
-
__new__ \ __metaclass__
1 2 3 4 5 6 7 8 |
|
上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象。
如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。
1 2 |
|
所以,f对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。
那么,创建类就可以有两种方式:
a). 普通方式
1 2 3 4 |
|
b). 特殊方式
1 2 3 4 5 6 7 |
|
这里给一个完整的例子:
def func(self):
print("hello %s"%(self.name))
def __init__(self,name):
self.name = name
oop = type('oop',(object,),{'talk':func,'__init__':__init__})
f = oop("agentxu")
f.talk() #hello agentxu
下面引用内容:
1 class MyType(type):
2 def __init__(self,*args,**kwargs):
3
4 print("Mytype __init__",*args,**kwargs)
5
6 def __call__(self, *args, **kwargs):
7 print("Mytype __call__", *args, **kwargs)
8 obj = self.__new__(self)
9 print("obj ",obj,*args, **kwargs)
10 print(self)
11 self.__init__(obj,*args, **kwargs)
12 return obj
13
14 def __new__(cls, *args, **kwargs):
15 print("Mytype __new__",*args,**kwargs)
16 return type.__new__(cls, *args, **kwargs)
17
18 print('here...')
19 class Foo(object,metaclass=MyType):
20
21
22 def __init__(self,name):
23 self.name = name
24
25 print("Foo __init__")
26
27 def __new__(cls, *args, **kwargs):
28 print("Foo __new__",cls, *args, **kwargs)
29 return object.__new__(cls)
30
31 f = Foo("Alex")
32 print("f",f)
33 print("fname",f.name)
类的生成 调用 顺序依次是 __new__ --> __init__ --> __call__
metaclass 详解文章:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python 得票最高那个答案写的非常好
这个效果在python2中能看得出来,python3没有什么效果。
4. 反射
hasattr(obj,name_str) , 判断一个对象obj里是否有对应的name_str字符串的方法
getattr(obj,name_str), 根据字符串去获取obj对象里的对应的方法的内存地址
setattr(obj,'y',z), is equivalent to ``x.y = v''
delattr(x,y) 删除x.y方法
# -*- coding:utf-8 -*-
# Author: Agent Xu
def bulk(self):
print("%s is yelling..." %(self.name))
class Dog(object):
def __init__(self,name):
self.name = name
def eat(self):
print("%s is eating..." %(self.name))
d = Dog("xiaohua")
func = input("the action is:").strip()
print(hasattr(d,func)) #判断输入的字符串是否属于类中定义的方法
getattr(d,func)() #xiaohua is eating... getattr()返回输入的字符串对应的类中定义的方法的地址
setattr(d,func,bulk)
d.talk(d) #xiaohua is yelling... 把类之外的函数加入类,并调用
delattr(d,func) #删除d.func
注:四种方法试验的时候要分开来操作,这样才能直观的看出结果。
5. 异常处理
异常处理的语句为:try:.........except:............
异常
try :
code
except (Error1,Erro2) as e:
print e
except Exception :抓住所有错误,不建议用
参考 http://www.cnblogs.com/wupeiqi/articles/5017742.html