python 类中的 self 即指代 当前类的命名空间, 私以为和 C++ 中的 this 关键字同义.
python 类 中的数据属性 和 局部变量一样, 无需声明, 第一次使用即可生成.
sample:
当然咯, 初始化类的对象, 如果要使之具有初始状态, 则可以在 __init__ 函数的参数列表中扩展参数列表.
sample:
数据属性会覆盖同名的方法属性, 为了避免意外的名称冲突,这在大型程序中是极难发现的 Bug,使用一些约定来减少冲突的机会是明智的。
函数定义代码不一定非得定义在类中:也可以将一个函数对象赋值给类中的一个局部变量。 例如:
每个值都是一个对象,因此每个值都有一个 类( class ) (也称为它的 类型( type ) ),它存储为 object.__class__ 。
继承:
若基类定义在另一个模块中, 则使用表达式继承
class DerivedClassName(modname.BaseClassName):
对于一个子类, 如果在类中找不到对应的属性, 就搜索基类, 在找到对应属性之前, 这个集合会按 基类链 递归上去.
isinstance() 用于检查实例类型: isinstance(obj, int) 只有在 obj.__class__ 是 int 或其它从 int 继承的类型
issubclass() 用于检查类继承: issubclass(bool, int) 为 True ,因为 bool 是 int 的子类。但是, issubclass(unicode,str) 是 False ,因为 unicode 不是 str 的子类(它们只是共享一个通用祖先类 basestring ).
在继承的时候,要注意命名空间的问题:
如下例: knife 也是student类对象s的一个属性, 但是age不是. 因为在people类中, age定义在方法中.
多继承:
若派生类 中找不到某属性, 那么在自然情况下: python会先从Base1 开始 dfs搜索它 的基类链, 若找不到, 则从Base2 开始dfs搜索它的基类链.
实际上, super()可以动态改变解析顺序
私有变量:
只能从对像内部访问的“私有”实例变量,在 Python 中不存在。然而,也有一个变通的访问用于大多数 Python 代码:以一个下划线开头的命名(例如 _spam )会被处理为 API 的非公开部分(无论它是一个函数、方法或数据成员)。它会被视为一个实现细节,无需公开。
因为有一个正当的类私有成员用途(即 避免子类里定义的命名与之冲突),Python 提供了对这种结构的有限支持,称为 name mangling (命名编码) 。任何形如 __spam 的标识(前面至少两个下划线,后面至多一个),被替代为 _classname__spam ,去掉前导下划线的 classname 即当前的类名。此语法不关注标识的位置,只要求在类定义内。
举例说明:
如上图所示, son类的对象s在初始化的时候, 调用 父类father的__init__方法, 方法最后调用了__update, 由于__update只在类father中有效, python会在father类中寻找__update的定义 , 发现 __update = update, 因此 python断定, 应当调用当前类中的update函数, 因此 程序的输出 为 "This is father' s update method !"
但是,若将__init__方法中的最后一行改为: "self.update(iterable)" , 则son类中的update方法会覆盖父类中的update方法, 程序的输出为 "This is son's update method !"
说到这里,突然想起override和overload
① override(重写)指的是子类的方法覆盖父类的方法,且方法名相同, 参数列表相同
② overload(重载)指的是两个方法的名字相同,但是参数列表不相同. 两方法可以在一个类中,也可以不在一个类中.
Pascal中的record 和 C中的struct 都可以将特定数据类型 捆绑在一起 , 构成一个新的数据结构:
python中直接使用类可以达到此目的:
代码如下:
异常也是类:
两种异常抛出形式:
① raise Class
② raise Instance
解释:
① raise Class 是 raise Class()的简写
② Instance 必须是Class或其派生类的一个实例
发生的异常类型如果是 except子句中列出的类或其派生类, 那么它们就是相符的
但是如果发生的异常类型是except子句中列出的类的基类,那么它们就是不相符的
一个例子:
屏幕将输出 C B A
迭代器:
大多数容器对象都可以使用for遍历
在后台, for语句在容器对象中调用iter(). 该函数返回一个定义了 next() 方法的迭代器对象,它在容器中逐一访问元素。
没有后续的元素时, next() 抛出一个 StopIteration 异常通知 for 语句循环结束.
在了解了迭代器协议的后台机制后, 定义一个 __iter__ 方法, 定义一个 __iter__() 方法,使其返回一个带有 next() 方法的对象。如果这个类已经定义了 next() ,那么 __iter__() 只需要返回 self:
一个例子:
生成器:
生成器(generator) 是一种可以很简单地实现迭代器的方式, 比写一个类(基于类的迭代器)更方便些. 需要返回数据时使用yield语句. 生成器会自动创建 __iter__方法 和 next 方法. 关键是, 在两次执行之间, 局部变量和执行状态都会被保存下来. 终结时, 它也会抛出 StopIteration 异常
一个例子:
此例将 正向输出 Coke Cola
生成器表达式:
这将在我的博文 "推导式与生成器表达式" 中和推导式一起介绍.
sample:
class M:
str = 'hello'
def __init__(self):
str = 'zhangpzh5'
x = M()
x.count = 5
print x.count
当然咯, 初始化类的对象, 如果要使之具有初始状态, 则可以在 __init__ 函数的参数列表中扩展参数列表.
sample:
class M:
str = 'hello'
count = 5
def __init__ (self , cnt):
self.count = cnt
def f(self):
return 'hello world'
x = M(10)
print x.count
输出5
注意到,实例对象x作为一个参数传给了函数. x= M(10)相当于 M.__init__(x,10)
x.f()相当于 M.f(x)
这就是所谓的 方法对象
数据属性会覆盖同名的方法属性, 为了避免意外的名称冲突,这在大型程序中是极难发现的 Bug,使用一些约定来减少冲突的机会是明智的。
函数定义代码不一定非得定义在类中:也可以将一个函数对象赋值给类中的一个局部变量。 例如:
# 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
每个值都是一个对象,因此每个值都有一个 类( class ) (也称为它的 类型( type ) ),它存储为 object.__class__ 。
继承:
class DerivedClassName(BaseClassName):
<statement-1>
.
.
.
<statement-N>
若基类定义在另一个模块中, 则使用表达式继承
class DerivedClassName(modname.BaseClassName):
对于一个子类, 如果在类中找不到对应的属性, 就搜索基类, 在找到对应属性之前, 这个集合会按 基类链 递归上去.
isinstance() 用于检查实例类型: isinstance(obj, int) 只有在 obj.__class__ 是 int 或其它从 int 继承的类型
issubclass() 用于检查类继承: issubclass(bool, int) 为 True ,因为 bool 是 int 的子类。但是, issubclass(unicode,str) 是 False ,因为 unicode 不是 str 的子类(它们只是共享一个通用祖先类 basestring ).
在继承的时候,要注意命名空间的问题:
如下例: knife 也是student类对象s的一个属性, 但是age不是. 因为在people类中, age定义在方法中.
class people:
knife = 5
def __init__(self):
age = 20.0
heigh = 175
def f(self):
return 'hello people'
def great(self):
return 'I love this world !'
class student(people):
def __init__(self):
ID = 12348157
def f(self):
return 'hello student'
s = student()
print s.knife
print s.great();
# print s.age
多继承:
class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
若派生类 中找不到某属性, 那么在自然情况下: python会先从Base1 开始 dfs搜索它 的基类链, 若找不到, 则从Base2 开始dfs搜索它的基类链.
实际上, super()可以动态改变解析顺序
私有变量:
只能从对像内部访问的“私有”实例变量,在 Python 中不存在。然而,也有一个变通的访问用于大多数 Python 代码:以一个下划线开头的命名(例如 _spam )会被处理为 API 的非公开部分(无论它是一个函数、方法或数据成员)。它会被视为一个实现细节,无需公开。
因为有一个正当的类私有成员用途(即 避免子类里定义的命名与之冲突),Python 提供了对这种结构的有限支持,称为 name mangling (命名编码) 。任何形如 __spam 的标识(前面至少两个下划线,后面至多一个),被替代为 _classname__spam ,去掉前导下划线的 classname 即当前的类名。此语法不关注标识的位置,只要求在类定义内。
举例说明:
class father:
def __init__(self,iterable):
self.myList = []
self.__update(iterable)
def update(self , iterable):
self.myList.append("This is father's update method !")
__update = update
class son(father):
def update(self, iterable):
self.myList.append("This is son's update method !")
list = []
s = son(list)
for string in s.myList:
print string,
如上图所示, son类的对象s在初始化的时候, 调用 父类father的__init__方法, 方法最后调用了__update, 由于__update只在类father中有效, python会在father类中寻找__update的定义 , 发现 __update = update, 因此 python断定, 应当调用当前类中的update函数, 因此 程序的输出 为 "This is father' s update method !"
但是,若将__init__方法中的最后一行改为: "self.update(iterable)" , 则son类中的update方法会覆盖父类中的update方法, 程序的输出为 "This is son's update method !"
说到这里,突然想起override和overload
① override(重写)指的是子类的方法覆盖父类的方法,且方法名相同, 参数列表相同
② overload(重载)指的是两个方法的名字相同,但是参数列表不相同. 两方法可以在一个类中,也可以不在一个类中.
Pascal中的record 和 C中的struct 都可以将特定数据类型 捆绑在一起 , 构成一个新的数据结构:
python中直接使用类可以达到此目的:
代码如下:
class Employment:
pass
John = Employment()
John.name = 'John.J.Rambo'
John.words = 'You won\'t beat me !'
异常也是类:
两种异常抛出形式:
① raise Class
② raise Instance
解释:
① raise Class 是 raise Class()的简写
② Instance 必须是Class或其派生类的一个实例
发生的异常类型如果是 except子句中列出的类或其派生类, 那么它们就是相符的
但是如果发生的异常类型是except子句中列出的类的基类,那么它们就是不相符的
一个例子:
class A(Exception):
pass
class B(A):
pass
class C(B):
pass
list = [C,B,A]
for l in list:
try:
raise l()
except C:
print 'C'
except B:
print 'B'
except A:
print 'A'
屏幕将输出 C B A
迭代器:
大多数容器对象都可以使用for遍历
在后台, for语句在容器对象中调用iter(). 该函数返回一个定义了 next() 方法的迭代器对象,它在容器中逐一访问元素。
没有后续的元素时, next() 抛出一个 StopIteration 异常通知 for 语句循环结束.
在了解了迭代器协议的后台机制后, 定义一个 __iter__ 方法, 定义一个 __iter__() 方法,使其返回一个带有 next() 方法的对象。如果这个类已经定义了 next() ,那么 __iter__() 只需要返回 self:
一个例子:
class Reverse:
def __init__(self,Str):
self.Str = Str
self.index = len(Str)
def __iter__(self):
return self
def __next__(self):
if(self.index == 0):
raise StopIteration
self.index -= 1
return self.Str[self.index]
next = __next__
rev = Reverse("zhangpzh")
for char in rev:
print char,
生成器:
生成器(generator) 是一种可以很简单地实现迭代器的方式, 比写一个类(基于类的迭代器)更方便些. 需要返回数据时使用yield语句. 生成器会自动创建 __iter__方法 和 next 方法. 关键是, 在两次执行之间, 局部变量和执行状态都会被保存下来. 终结时, 它也会抛出 StopIteration 异常
一个例子:
def forward(data):
for index in range(0,len(data),1):
yield data[index]
for char in forward('Coke Cola'):
print char,
此例将 正向输出 Coke Cola
生成器表达式:
这将在我的博文 "推导式与生成器表达式" 中和推导式一起介绍.