@XQF
2016-07-31T11:40:30.000000Z
字数 4501
阅读 1018
Python快速教程-----实验楼
Python学习告一段落,下面部分,讨论的是Python的高级语法和底层实现
多范式语言,不仅可以使用面向对象的方式来变形额程序(还有函数式,声明式),多范式是依赖于Python对象的特殊方法
特殊方法前后各有一个下划线定义了许多的语法和表达方式,正如我们在下面的例子中将要看到的,当对象中定义了特殊方法的时候会有特殊对待
Python的运算符是通过调用对象的特殊方法实现的
'abc'+'xyz'
实际上是执行了
'abc'._add_('xyz')
的操作
所以看是否能进行加法运算就看是否有add()方法,运算符气道简化书写的功能,但是是依靠特殊方法实现的
不强制用户使用面向对象的编程方法,可以使用自己喜欢的方式尽心编程
与运算符类似,许多的内置函数也都是调用对象的特殊方法
len([1,2,3])
实际上是
[1,2,3]._len_(),内置函数len()也起到了假话书写的作用
下面是我们常用的表元素引用方式
li=[1,2,3,4,5]
print (li[3])
程序运行到li[3]的时候,Python发现并理解[]符号,然后调用getitem()方法
li=[1,2,3,4,5]
print (li._getitem_(3))
我们已经说过,在Python中,函数也是一种对象,实际上,任何一个有call()特殊方法的对象都被当作是函数,
class SampleMore(object):
def _call()_(self,a):
return a+5
add=SampleMore() #add被当作函数
print (add(2))
map(add,[2,4,5]) #函数作为参数
用于规定某个对象的使用范围。一旦进入或者离开该使用范围,会有特殊操作被调用(比如对象分配或者内存释放),语法形式为 with...as....
上下文管理器可以在不需要文件的时候自动关闭文件
f=open("new.txt","w")
print (f.closed) #whether the file is open
f.write("hello world")
f.close()
print (f.closed)
使用了上下文管理器的程序
with open("new.txt","w") as f:
print (f.closed)
f.write("hello world")
print (f.closed)
手动测试确实是自动关闭了
上下文管理器有隶属于它的程序块,当程序块结束的时候(也就是 不再缩进),上下文管理器自动关闭了文件(我们通过f.closed来查询是否已经关闭了文件),我们相当于使用缩进规定了文件对象f的使用范围
当我们使用上下文管理器的语法时,我们实际上要求Python在进入程序之前调用对象的_enter_()方法,结束程序块的时候调用_exit_()方法。对于文件对象来说,它定义了这两个方法,在_exit_()方法中,有self.close()语句,所以在使用上下文管理器时,我们就不需要明文关闭文件了
任何定义了enter()和exit()方法的对象都可以用于上下文管理器,文件对象
是f的内置对象,所以f自动带有这两个特殊方法,不需要自定义。我们可以自己定制上下文管理器的对象
class VOW(object):
def _init_(self,text):
self.text=text
def _enter_(self):
self.text="I say "+self.text
return self
def _exit_(seelf,exc_type,exc_value,traceback)
self.text=self.text+"!"
with VOW("I'm fine") as myvow:
print (myvow.text)
print my.text
运行结果
I say:I'm fine
I say:I'm fine!
可以看到在进入上下文和离开上下文的时候,对象的text属性发生了改变
enter()返回一个对象,上下文管理器会使用这一对象作为as所指的变量,也就是myvow.在enter()中,我们为myvow.text增加了前缀,在exit()中我们增加了后缀。在进入管理器时使用——enter_()方法,最后发现已经不再使用这个文件了,就需要自动关闭,在自动关闭的时候就使用exit()方法因此使用的顺序是这样的,没有退出前是没有使用exit()方法的
_exit_()方法中有四个参数,当程序块中出现了异常,参数中的exc_type,exc_value,traceback就用于描述异常。可以根据这三个异常进行处理,要是程序正常运行结束,这三个参数的值都是None
一切皆为对象,因此有一套统一的管理方案
对象的属性可能来自于类定义,叫做类属性(class attribute).类属性也可以根据类定义继承而来。一个对象的属性还可能是该对象实例定义的,叫做对象属性
对象的属性存储在对象的dict属性当中,dict为一个词典,键为属性名,对应的键值为属性本身。
示例代码:
class bird(object):
feather=True
class chicken(bird):
fly=False
def __init__(self,age):
self.age=age
summer=chicken(2)
print (bird.__dict__)
print (chicken.__dict__)
print (summer.__dict__)
输出
{'__dict__': <attribute '__dict__' of 'bird' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'bird' objects>, 'feather': True, '__doc__': None}
{'fly': False, '__module__': '__main__', '__doc__': None, '__init__': <function __init__ at 0x02AE77F0>}
{'age': 2}
第一行为bird类的属性。有我们自定义的属性feather,也有python自动生成的doc属性等等
第二行为chicken类的属性,有自定义的fly,init和继承而来的module等等
第三行为summmer对象的属性
Python的属性定义是分层的,当我们需要调用某个属性的时候,Python会一层层向上进行遍历,直到找到那个属性(优先选取先遇到的那一个)
有两种方式修改对象属性
summer.__dict__['age']=3
print(summer.__dict__['age'])
summer.age=5
print (summer.age)
要是我们偶遇一个完全不知道的对象,可以通过class属性找到对象的类,通过调用类的base属性来查询父类
同一个对象的不同属性之间可能存在依赖关系,当某个属性修改时,希望依赖于该属性的其他属性也要同时变化,这时不能通过dict的方式来静态改变存储属性。Python提供了多种即时生成属性的方法,其中一种称为特性(property),特性是特殊的属性。原来是一个方法
示例:
class bird(object):
feather=True
class chicken(bird):
fly=False
def __init__(self,age):
self.age=age # 与fly的定义是相差无几
def getAdult(self):
if self.age>1.0:return True #做一个判断
else :return False
adult=property(getAdult)# adult属性与age属性有关联,使用函数作为参数,这一句也叫增加一个adult特性
summer=chicken(2)
print (summer.adult)
summer.age=0.5 #做一个改变
print(summer.adult)
特性使用内置函数property()来创建,最多可以加载四个参数,前撒个为函数,分别用于处理查询特性,修改特性,删除特性。最后一个为特性的文档,可以为一个字符串。起说明作用。
下面实例
class num(object):
def __init__(self,value):
self.value=value
def getNeg(self):
return -self.value
def setNeg(self,value):
self.value=-value
def delNeg(self):
print("value also deleted")
del self.value
neg=property(getNeg,setNeg,delNeg,"I'm negative")
x=num(1.1)
print (x.neg)
print(x.value)
print(num.neg.__doc__)
del x.neg #这个操作是删除特性
num()为一个数字,而neg为一个特性,用来表示数字的负数,value为数字的值,因此我们给了一个正数1.1,value为1.1,neg为-1.1,doc为说明文档,前三个参数正好是函数参数对象
我们可以使用这个方法getattr(self,name)查询即时生成的属性,当我们查询一个属性时,如果通过dict()方法无法找到该属性,那么Python会调用对象的getattr方法,来即时生成该属性(应该就是说我们并没有明确的定义这个属性,而是在这个方法中有一定的操作,要是这个方法中仍然没有,就只能报错了
class bird(object):
feather=True
class chicken(bird):
fl=Flase
def _init_(self,age):
self.age=age
def _getattr_(self,name):
if name=='adult':
if self.age>1.0:return True
else : return False
else :raise AttributeError(name)
summer=chicken(2)
print (summer.adult)
summer.age=0.5
每个特性需要有自己的处理函数,而getatt可以将所有的即时生成属性放在同一个函数中处理。getattr可以根据函数名区别处理不同的属性。比如上面我们查询属性名male的时候,raise AttributeError
Python中还有一个方法getattrbute这个特殊方法,用于查询任意属性。getattr只能用来查询不在dict系统中的属性
setattr(self,name,value)和delattr(self,name)可用于修改和删除属性,应用更加广泛,可用于任意属性