[关闭]
@XQF 2016-07-31T11:40:30.000000Z 字数 4501 阅读 1018

Python深入(上)

Python快速教程-----实验楼


Python学习告一段落,下面部分,讨论的是Python的高级语法和底层实现

特殊方法与多范式

多范式语言,不仅可以使用面向对象的方式来变形额程序(还有函数式,声明式),多范式是依赖于Python对象的特殊方法
特殊方法前后各有一个下划线定义了许多的语法和表达方式,正如我们在下面的例子中将要看到的,当对象中定义了特殊方法的时候会有特殊对待

运算符

Python的运算符是通过调用对象的特殊方法实现的

'abc'+'xyz'

实际上是执行了

'abc'._add_('xyz')

的操作

所以看是否能进行加法运算就看是否有add()方法,运算符气道简化书写的功能,但是是依靠特殊方法实现的

不强制用户使用面向对象的编程方法,可以使用自己喜欢的方式尽心编程

内置函数

与运算符类似,许多的内置函数也都是调用对象的特殊方法

len([1,2,3])

实际上是

[1,2,3]._len_(),内置函数len()也起到了假话书写的作用

表(list)的元素引用

下面是我们常用的表元素引用方式

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()特殊方法的对象都被当作是函数,

  1. class SampleMore(object):
  2. def _call()_(self,a):
  3. return a+5
  4. add=SampleMore() #add被当作函数
  5. print (add(2))
  6. map(add,[2,4,5]) #函数作为参数

上下文管理器

用于规定某个对象的使用范围。一旦进入或者离开该使用范围,会有特殊操作被调用(比如对象分配或者内存释放),语法形式为 with...as....

关闭文件

上下文管理器可以在不需要文件的时候自动关闭文件

  1. f=open("new.txt","w")
  2. print (f.closed) #whether the file is open
  3. f.write("hello world")
  4. f.close()
  5. print (f.closed)

使用了上下文管理器的程序

  1. with open("new.txt","w") as f:
  2. print (f.closed)
  3. f.write("hello world")
  4. print (f.closed)

手动测试确实是自动关闭了
上下文管理器有隶属于它的程序块,当程序块结束的时候(也就是 不再缩进),上下文管理器自动关闭了文件(我们通过f.closed来查询是否已经关闭了文件),我们相当于使用缩进规定了文件对象f的使用范围

当我们使用上下文管理器的语法时,我们实际上要求Python在进入程序之前调用对象的_enter_()方法,结束程序块的时候调用_exit_()方法。对于文件对象来说,它定义了这两个方法,在_exit_()方法中,有self.close()语句,所以在使用上下文管理器时,我们就不需要明文关闭文件了

自定义

任何定义了enter()和exit()方法的对象都可以用于上下文管理器,文件对象是f的内置对象,所以f自动带有这两个特殊方法,不需要自定义。我们可以自己定制上下文管理器的对象

  1. class VOW(object):
  2. def _init_(self,text):
  3. self.text=text
  4. def _enter_(self):
  5. self.text="I say "+self.text
  6. return self
  7. def _exit_(seelf,exc_type,exc_value,traceback)
  8. self.text=self.text+"!"
  9. with VOW("I'm fine") as myvow:
  10. print (myvow.text)
  11. 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

对象的属性

一切皆为对象,因此有一套统一的管理方案

属性的dict系统

对象的属性可能来自于类定义,叫做类属性(class attribute).类属性也可以根据类定义继承而来。一个对象的属性还可能是该对象实例定义的,叫做对象属性
对象的属性存储在对象的dict属性当中,dict为一个词典,键为属性名,对应的键值为属性本身。
示例代码:

  1. class bird(object):
  2. feather=True
  3. class chicken(bird):
  4. fly=False
  5. def __init__(self,age):
  6. self.age=age
  7. summer=chicken(2)
  8. print (bird.__dict__)
  9. print (chicken.__dict__)
  10. 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),特性是特殊的属性。原来是一个方法
示例:

  1. class bird(object):
  2. feather=True
  3. class chicken(bird):
  4. fly=False
  5. def __init__(self,age):
  6. self.age=age # 与fly的定义是相差无几
  7. def getAdult(self):
  8. if self.age>1.0:return True #做一个判断
  9. else :return False
  10. adult=property(getAdult)# adult属性与age属性有关联,使用函数作为参数,这一句也叫增加一个adult特性
  11. summer=chicken(2)
  12. print (summer.adult)
  13. summer.age=0.5 #做一个改变
  14. print(summer.adult)

特性使用内置函数property()来创建,最多可以加载四个参数,前撒个为函数,分别用于处理查询特性,修改特性,删除特性。最后一个为特性的文档,可以为一个字符串。起说明作用。
下面实例

  1. class num(object):
  2. def __init__(self,value):
  3. self.value=value
  4. def getNeg(self):
  5. return -self.value
  6. def setNeg(self,value):
  7. self.value=-value
  8. def delNeg(self):
  9. print("value also deleted")
  10. del self.value
  11. neg=property(getNeg,setNeg,delNeg,"I'm negative")
  12. x=num(1.1)
  13. print (x.neg)
  14. print(x.value)
  15. print(num.neg.__doc__)
  16. del x.neg #这个操作是删除特性

num()为一个数字,而neg为一个特性,用来表示数字的负数,value为数字的值,因此我们给了一个正数1.1,value为1.1,neg为-1.1,doc为说明文档,前三个参数正好是函数参数对象

使用特殊方法 getattr

我们可以使用这个方法getattr(self,name)查询即时生成的属性,当我们查询一个属性时,如果通过dict()方法无法找到该属性,那么Python会调用对象的getattr方法,来即时生成该属性(应该就是说我们并没有明确的定义这个属性,而是在这个方法中有一定的操作,要是这个方法中仍然没有,就只能报错了

  1. class bird(object):
  2. feather=True
  3. class chicken(bird):
  4. fl=Flase
  5. def _init_(self,age):
  6. self.age=age
  7. def _getattr_(self,name):
  8. if name=='adult':
  9. if self.age>1.0:return True
  10. else : return False
  11. else :raise AttributeError(name)
  12. summer=chicken(2)
  13. print (summer.adult)
  14. summer.age=0.5

每个特性需要有自己的处理函数,而getatt可以将所有的即时生成属性放在同一个函数中处理。getattr可以根据函数名区别处理不同的属性。比如上面我们查询属性名male的时候,raise AttributeError

Python中还有一个方法getattrbute这个特殊方法,用于查询任意属性。getattr只能用来查询不在dict系统中的属性

setattr(self,name,value)和delattr(self,name)可用于修改和删除属性,应用更加广泛,可用于任意属性

即时生成属性的其他方式

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注