python完全具备面向对象的特质:类的实例化、类元素调用、继承、多层继承、覆盖,并且还有自己独特的语法定义。
class ClassName:
<statement-1>
.
.
.
<statement-N>
一旦完成一个类的编写,同时一个名称为ClassName的命名空间被定义,可以提供给其它类引用,里面的成员有属性成员于方法成员。
类对象支持:属性引用与实例化
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
其中 MyClass.i、MyClass.f都是合法的属性引用,可以给MyClass.i赋值,其中__doc__是类中的注释信息。
当一个类建立起来后,可以通过初始化函数进行初始化一些数据,python用的就是 **init()**方法:
>>> class Complex:
... def __init__(self, realpart, imagpart):
... self.r = realpart
... self.i = imagpart
...
>>> x = Complex(3.0, -4.5)
>>> x.r, x.i
(3.0, -4.5)
实例对象唯一能理解的操作就是属性引用. 有两种合法的属性, 数据属性和方法
class classdemo:
field='meimei:'
def __init__(self,key,value):
self.r=key
self.y=value
def PrintString(self,values):
print self.field,values
u=classdemo(4,5)
print u.r,u.y
u.PrintString('is a female!')
u.field='peter:'
u.PrintString('is a male!')
>4 5
>meimei: is a female!
>peter: is a male!
方法对象绑定后就可以调用了。
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
x = MyClass()
x.f()
xf = x.f
while True:
print xf()
**x.f() 针对方法的调用,可以保存起来,xf 到后面进行调用。
作为类属性的任何函数对象, 定义了一个方法用于那个类的实例. 函数是否在一个类体中其实并不重要: 指定一个函数对象给类中的局部变量也是可以的:
# Function defined outside the class
def f1(self, x, y):
return min(x, x+y)
class C:
f = f1
def g(self):
return 'hello world'
h = g
我们知道了方法的第一个参数默认是self,所以我们可以在同一个类中的方法可以通过self互相调用:
class Bag:
def __init__(self):
self.data = []
def add(self, x):
self.data.append(x)
def addtwice(self, x):
self.add(x)
self.add(x)
x=Bag()
x.add(1)
x.addtwice(2)
print x.data
[1, 2, 2]
派生类定义如下:
class DerivedClassName(BaseClassName):
<statement-1>
.
.
.
<statement-N>
BaseClassName 的定义对于派生类而言必须是可见的. 在基类的地方, 任意的表达式都是允许的. 这就会非常有用, 比如基类定义在另一个模块:
class DerivedClassName(modname.BaseClassName):
Python 支持多重继承. 一个多重继承的类定义看起来像这样:
class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
在方法成员中定义一个私有的属性,供类中的其它方法调用:
class Mapping:
def __init__(self, iterable):
self.items_list = []
self.__update(iterable)
def update(self, iterable):
for item in iterable:
self.items_list.append(item)
__update = update # private copy of original update() method
class MappingSubclass(Mapping):
def update(self, keys, values):
# provides new signature for update()
# but does not break __init__()
for item in zip(keys, values):
self.items_list.append(item)
像写个抽象函数一样我们可以定义一个空的类,然后给这个类附加一些数据属性,具体怎么用,需要在实战中体现:
class Employee:
pass
john = Employee() # Create an empty employee record
# Fill the fields of the record
john.name = 'John Doe'
john.dept = 'computer lab'
john.salary = 1000
用户定义的异常其实也是类. 使用这个机制, 就可以创建可扩展的异常继承体系.
有两种合法的形式用于 raise 语句:
raise Class
raise Instance
一个在 except 中的类, 可以与一个异常相容, 如果该异常是同样的类, 或是它的基类 (但是并不是另一种 – 一个 except 语句列出的派生类与其基类并不相容). 如下面的代码, 以那种顺序打印出 B, C, D:
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
for c in [B, C, D]:
try:
raise c()
except D:
print("D")
except C:
print("C")
except B:
print("B")
大多数的容器对象都可以使用 for 来迭代:
for element in [1, 2, 3]:
print(element)
for element in (1, 2, 3):
print(element)
for key in {'one':1, 'two':2}:
print(key)
for char in "123":
print(char)
for line in open("myfile.txt"):
print(line)
这种形式简洁, 明了并且方便. 迭代器的使用遍布于 Python 之中. 在这个外表之下,
for 语句对容器对象调用了 iter(). 这个函数返回一个迭代器对象, 它定义了 next() 方法,
用以在每次访问时得到一个元素. 当没有任何元素时, next() 将产生 StopIteration 异常,
它告诉 for 停止迭代. 你可以使用内置函数 next() 来调用 next() 方法; 这个例子展示了它如何工作:
>>> s = 'abc'
>>> it = iter(s)
>>> it
<iterator object at 0x00A1DB50>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
next(it)
StopIteration
在看到迭代器的机制之后, 就可以很简单的将迭代行为增加到你的类中. 定义一个 iter() 方法用以返回一个具有 next() 的对象.
如果这个类定义了 next() , 那么 iter() 仅需要返回 self:
class Reverse:
"Iterator for looping over a sequence backwards"
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
>>> rev = Reverse('spam')
>>> iter(rev)
<__main__.Reverse object at 0x00A1DB50>
>>> for char in rev:
... print(char)
...
m
a
p
s
Generator (生成器) 是一个用于创建迭代器简单而且强大的工具. 它们和普通的函数很像, 但是当它们需要返回值时, 则使用 yield 语句.
每次 next() 被调用时, 生成器会从它上次离开的地方继续执行 ( 它会记住所有的数据值和最后一次执行的语句).
一个例子用以展示如何创建生成器:
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
>>> for char in reverse('golf'):
... print(char)
...
f
l
o
g
有些简单的生成器可以简洁的写出来, 而且和列表推导很类似, 仅仅是将方括号换成了圆括号.
这些表达式设计用于在一个函数中正好可以用生成器的情况. 生成器表达式更加紧密,
但是功能相对来说也少点, 并且与同样的列表推导式来说更节约内存.
>>> sum(i*i for i in range(10)) # sum of squares
285
>>> xvec = [10, 20, 30]
>>> yvec = [7, 5, 3]
>>> sum(x*y for x,y in zip(xvec, yvec)) # dot product
260
>>> from math import pi, sin
>>> sine_table = {x: sin(x*pi/180) for x in range(0, 91)}
>>> unique_words = set(word for line in page for word in line.split())
>>> valedictorian = max((student.gpa, student.name) for student in graduates)
>>> data = 'golf'
>>> list(data[i] for i in range(len(data)-1, -1, -1))
['f', 'l', 'o', 'g']