9. 类
来源:互联网 发布:西安财经行知特点 编辑:程序博客网 时间:2024/06/05 15:56
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 = 5print x.count
当然咯, 初始化类的对象, 如果要使之具有初始状态, 则可以在 __init__ 函数的参数列表中扩展参数列表.
sample:
class M: str = 'hello' count = 5def __init__ (self , cnt): self.count = cntdef 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 classdef 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.knifeprint 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 = updateclass 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:passJohn = 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): passclass B(A): passclass C(B): passlist = [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
生成器表达式:
这将在我的博文 "推导式与生成器表达式" 中和推导式一起介绍.
0 0
- 9. 类
- 9. 类
- 9.类,对象,方法
- 9.包装类
- 9.C++类构造函数
- 9.Swift-类和结构体
- 9.抽象类和抽象函数
- 【JAVA SE】9.类和对象
- <C++>9.类成员函数的定义
- 【Allwinner ClassA20类库分析】9.WatchDog类的使用
- 9.定时器的使用以及CTime类的使用
- [JAVA · 初级]:9.Object类提供的常用方法
- Swift3.0中文教程: 9.类和结构体
- Python高级编程——9.元类
- 【c++基础】9.类和对象——类的实现2
- [ASP中使用三层架构] 9.用户登录之一 User表与相关类
- 9.c++-尽量用const和inline而不用#define,类静态成员变量和函数
- 《深入解析MFC》笔记 9.MFC的增强型用户界面类
- 8. 错误和异常
- SQL结合作业实现将一个表的数据抓到另一个表中
- 【Leetcode】two sum JAVA
- Android Studio酷炫插件(一)——自动化快速实现Parcelable接口序列化
- html5调用手机摄像头,实现拍照上传功能
- 9. 类
- 树莓派+一根网线直连笔记本电脑
- The Linux Graphics Stack
- Objective-C语言关键词,@class
- Unity3d AssetDatabase.SetLabels StartAssetEditing ValidateMoveAsset 语法复习
- LeetCode Symmetric Tree
- HDOJ 3555 Bomb
- ubuntu配置ssh
- 在Java中使用weka:入门