【继承示意图】

类是实例的工厂, OOP就是在树中搜索属性,类事实上就是变量名与函数打成的包

. 每一个class语句会生成一个新的类对象

. 每次类调用时,就会生成一个新的实例对象

. 实例自己主动连接到创建这些实例的类

. 类连接到超类的方式是,将超类列在类头部(),其从左到右的顺序会决定树中的次序

有几点须要注意:

. 属性一般是在class语句中通过赋值语句加入在类中,而不是嵌入函数的def语句中

. 属性一般是在类中,对传给函数的特殊參数self。做赋值运算而加入在实例中的

【方法调用的两种方式】

def 语句出如今类中。通常称为方法:

通过实例调用:bob.giveRise()

通过类来调用:Employee.giveRise(bob)

【类与模块】

从最底层来看,类差点儿就是命名空间,非常像模块。但和模块不同的之处是:

1. 类也支持多个对象的产生(多态)

2. 命名空间继承(继承)

3. 运算符重载(重载)

【PYTHON类的主要特点】

. class语句创建对象并将其赋值给变量名(类似于def)

. class语句内的赋值语句会创建类的属性(属性获得:object.name)

. 类属性提供对象的状态和行为

【类的实例概要】

. 像函数那样调用对象会创建新的实例对象

. 每一个实例对象继承类的属性并获得自己的命名空间

. 在方法内对self属性做赋值运算会产生每一个实例自己的属性

【第一个样例】

class FirstClass:              #定义类的对象

    def setdata(self,value):   #定义类方法

        self.data = value      #self是个实例

    def display(self):

        print self.data        #self-data: 每一个实例共享

创建两个实例,每一个实例拥有自己的命名空间

>>> x = FirstClass()

>>> y = FirstClass()

会产生三个对象: 两个实例,一个类

>>> x.setdata('Hello')     #调setdata方法,self就是x本身

>>> y.setdata(100)         #执行: FirstClass.setdata(y,100)

x,y创建不同实例对象的命名空间,所以虽然都调用display方法,值却不同

>>> x.display()            #self.data在每一个实例中不一样

Hello

>>> y.display()

100

还有一种调用方式:

>>> x.data = "New Value"   #可以获得或设置属性

>>> x.display()

New Value

也能够设置成一个全新的属性

>>> x.anothername = 'spam'

【PYTHON类继承的核心观点】

. 超类列在类开头的括号里

. 类从超类中继承属性,当读入属性时,假设不存在于子类中,PYTHON会自己主动搜索这个属性

. 实例会继承全部可读取类的属性. 搜索路径: 实例 ==> 创建实例的类 ==> 全部超类

. 每一个object.attribute都会开启新的独立搜索

. 逻辑的改动是通过创建子类,而不是改动超类

这样的搜索的结果及主要目的就是:

第一: 类支持了程序的分解和定制。比迄今为止所见到的其它不论什么语言工具都要好。

第二: 能够把程序的冗余度降到最低。降低维护成本。也就是把操作分解为单一,共享的实现

第三: 这样敲代码时。也能够让我们队现有的程序代码进行定制,而不是实地改动或从头開始

【第二个样例】

class SecondClass(FirstClass):     #继承FirstClass类中的setdata方法

    def display(self):             #改动display方法,也叫方法的重载

        print 'Current value = %s' % self.data

搜索从实例開始==>子类==>超类,直到找到第一个为止,所以display会覆盖父类方法

>>> z = SecondClass()

>>> z.setdata('Hello,World!')      #从FirstClass中发现setdata方法

>>> z.display()                    #SecondClass中发现display方法

Current value = Hello,World!

NOTE:作为一条规则,由于继承能够让我们在外部组件内(也就是在子类内)进行改动。类所支持的扩展和重用通常比函数或模块更好!

【第三个样例】: 关于运算符重载

定义SecondClass的子类,实现三个特殊名称的属性,让PYTHON自己主动调用:

当新的实例构造时,会调用__init__(self是新的ThirdClass对象)

当ThirdClass实例出如今+或*表达式中时。则分别调用__add__和__mul__

class ThirdClass(SecondClass):                 #ThirdClass类,继承自SecondClass

    def __init__(self,value):                  #ThirdClass类中的值

        self.data = value

    def __add__(self,other):                   #注意这样的调用方式 self + other

        return ThirdClass(self.data + other)

    def __mul__(self,other):

        self.data = self.data * other          #self * other

运行结果:

>>> a = ThirdClass('AB')                       #调用__init__构造函数

>>> a.display()                                #继承的方法

Current value = AB

>>> b = a + 'XY'                               #新的__add__:造一个新的实例

>>> b.display()

Current value = ABXY

>>> a * 3                                      #新的__mul__:在当地改变实例

>>> a.display()

Current value = ABABAB

NOTE:

__add__方法创建并返回这个类的新的实例对象

__mul__方法会在原处改动当前的实例对象

【OOP最重要的两个概念】

方法函数中的特殊self參数和__init__构造器方法是PYTHON中OOP的两个基石

【最经常使用的运算符重载】

运算符重载是由特定名称的方法写成的。

这些方法的开头和结尾都是双下划线,通过这样的方法使其变得独特。这些不是内置或保留字。

当实例出如今相应的运算中时。PYTHON就会自己主动运行它们。

PYTHON为这些运算和特殊方法的名称定义了相应的关系。

__init__构造器是最经常使用的。差点儿每一个类都使用这种方法为实例属性进行初始化,以及运行其它的启动任务。

【变量名同样的样例】

class MixedNames:                  #定义类:MixedNames

data = 'spam'              #赋值类属性:data



def __init__(self,value):  #赋值方法名:  

self.data = value  #赋值实例属性:data



def display(self):

print MixNames.data,self.data   #类属性,实例属性

输出结果:

>>> ins1 = MixedNames(1)       #类工厂造两个实例对象x,y

>>> ins2 = MixedNames(2)       #每一个实例对象有自己的数据

>>> ins1.display();ins2.display() #self.data不同,subclass.data却是同样的。都是从data = 'spam'继承而来

spam 1

spam 2

>>> MixedNames.display(ins1)   #这样的写也是能够的

【还有一个样例】

message = 'Global Message!'

class NextClass:

    message = 'Class Message'



    def printer(self,value):

self.message = value

print 'message', message

print 'NextClass.message',NextClass.message

print 'self.message',self.message

输出结果:

>>> x = NextClass()                     #造实例

>>> x.printer('Instance Message!')      #调实例的方法

message is:            Global Message!

NextClass.message is:  Class Message!

self.message is:       Instance Message!

其它调用:

>>> NextClass.printer(x,'class call')    #正确:直接调用类

>>> NextClass.printer('class call')      #错误:必须在第一个位置放实例名

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

TypeError: unbound method printer() must be called with NextClass instance as first argument (got str instance instead)

【调用超类的构造器】

假设除了想调用自身的构造函数。还想调用超类的。那么就必须用以下的方式

class Super:

def __init__(self,x):

pass



class Sub(Super):

def __init__(self,x,y):

Super.__init__(self.x)

pass

I = Sub(1,2)

【继承方法的专有化】

继承树搜索模式是将系统专有化的最好的方式。继承会先在子类中寻找变量名,然后才查找超类。子类能够对超类的属性又一次定义来代替默认的行为。

实际上,能够把整个系统做成类的层次,再新增外部的子类来对其进行扩展,而不是在原处改动已重载的逻辑。

. 子类能够全然代替继承的属性

. 子类能够找到并获得超类属性

. 子类能够通过已覆盖的方法回调超类来扩展超类的方法

class Super:

def method(self):

print 'start Super.method'



class Sub(Super):

def method(self):                           #重写方法

print 'starting Sub.method'         #添加行为

Super.method(self)                  #执行默认的行为,NOTE:self的使用

print 'ending Super.method'

直接调用超类方法是这里的重点。Sub类代替了Super的方法函数.可是。代替时。Sub又回调了Super所导出的版本号,从而实现了默认的行为。也就是说:Sub.method仅仅是扩展了Super.method的行为,而不是全然代替。

输出结果:

>>> x = Super()                                     #造一个Super实例

>>> x.method()                                      #调Super类中的method方法

Start Super.method

>>> x = Sub()                                       #造一个Sub实例

>>> x.method()                                      #调Sub类中的method,当中又回调了父类的方法

Start Sub.method

Start Super.method

Ending Super.method

【类接口技术】

扩展仅仅是一种同超类接口的方式。以下示范了specialize.py文件定义了多个类,示范了一些经常使用的技巧

Super:     定义了一个method函数以及一个delegate函数

Inheritor: 没有提供不论什么新的变量名,因此会获得Super中定义的一切内容

Replacer:  用自己的版本号来覆盖Super的method

Extender:  覆盖并回调默认的method。从而定制Super的method

Provider:  实现Super的delegate方法预期的action方法

#File:  specialize.py

<span style="font-family:SimHei;font-size:14px;">class Super:
def method(self):
print 'in Super.method'
def delegate(self):
self.action() class Inheritor(Super):
pass class Replacer(Super):
def method(self):
print 'in Replacer.method' class Extender(Super):
def method(self):
print 'starting Extender.method'
Super.method(self)
print 'ending Extender.method' class Provider(Super):
def action(self):
print 'in Provider.action' if __name__=='__main__':
for klass in (Inheritor,Replacer,Extender):
print '\n' + klass.__name__ + '...'
klass().method()
print '\nProvider...'
x = Provider()
x.delegate()</span>

NOTE:

1. 末尾的自我測试代码在for循环中建立三个不同类的实例

2. 类也有特殊的__name__属性,就像模块。

它默认类首行中的类名称的字符串

执行结果:

D:\>python specialize.py



Inheritor...

in Super.method



Provider...

in Provider.action



Replacer...

in Replacer.method



Provider...

in Provider.action



Extender...

starting Extender.method

in Super.method

ending Extender.method



Provider...

in Provider.action

【抽象超类】

上例中的Provider类中,当通过Provider实例调用delegate方法时,两个独立的继承搜索将会发生:

1. 在最初的x.delegate调用中。PYTHON会搜索Provider实例和它上层的对象,知道在Super中找到delegate的方法。实例x会像往常一样传递给这种方法的self參数

2. 在Super.delegate方法中,self.action会对self以及它上层的对象启动新的独立继承搜索。由于self指的是Provider实例,就会找到Provider子类中的action

这样的填空式的代码结构一般就是OOP的软件框架。从delegate方法的角度来看。这个样例中的超类也称为抽象类--也就是类的部分行为默认是由其子类来实现。

假设逾期的方法没有在子类中定义。当继承搜索失败时,PYTHON会引发没有定义变量名的异常。

通常会使用assert语句。使这样的子类须要更为明显,或者引发内置的异常NotImplementedError:

<span style="font-family:SimHei;font-size:14px;">class Super:

	def method(self):
print 'In Super.method' def delegate(self):
self.action def action(self):
assert 0, 'action must be defined!'</span>

【运算符重载】

. 运算符重载让类拦截常规的PYTHON运算

. 类可重载全部PYTHON表达式运算符

. 类可重载打印、函数调用、属性点号运算等运算

. 重载使类实例的行为像内置类型

. 重载是通过特殊名称的类方法实现的

简单样例

<span style="font-family:SimHei;font-size:14px;">class Number:
def __init__(self,start): #on Number(start)
self.data = start def __sub__(self,other): #On instance - other
return Number(self.data - other) #Result is a new instance</span>

输出结果:

>>> from number import Number  #Fetch class from Module

>>> X = Number(5)              #Number.__init__(X,5)

>>> Y = X -2                   #Number.__sub__(X,2)

>>> Y.data                     #Y is new Number instance

3

【常见的运算符重载】

【__getitem__拦截索引运算】

以下的类将返回索引值的平方

<span style="font-family:SimHei;font-size:14px;">class indexer:
def __getitem__(self,index):
return index ** 2</span>

输出结果:

<span style="font-family:SimHei;font-size:14px;">>>> X = indexer()
>>> X[2]
4
>>> for i in range(5):
... print X[i],
...
0 1 4 9 16</span>

【__getitem__和__iter__实现迭代】

<span style="font-family:SimHei;font-size:14px;">class stepper:
def __getitem__(self,i):
return self.data[i]
</span>

输出结果:

<span style="font-family:SimHei;font-size:14px;">>>> X = stepper()         #X is a stepper object
>>> X.data = 'spam'
>>> X[1] #Indexing calls __getitem__
'p'
>>> for item in X: #for loops call __getitem__
... print item, #for index items 0..N
...
s p a m</span>

其它的一些引用:

>>> 'p' in X

True

>>> [c for c in X]

['s', 'p', 'a', 'm']

>>> map(None,X)

['s', 'p', 'a', 'm']

>>> (a,b,c,d) = X

>>> a,c,d

('s', 'a', 'm')

>>> list(X);tuple(X);''.join(X)

['s', 'p', 'a', 'm']

('s', 'p', 'a', 'm')

'spam'

>>> X

<number.stepper instance at 0x00000000025EE088>

【__getattr__和__setattr__捕捉属性的引用】

__getattr__方法是拦截属性点号运算。当通过没有定义属性名称和实例进行点号运算时,就会用属性名称为字符串调用这种方法。

__getattr__样例:

class empty:

def __getattr__(self,attrname):

if attrname == "age":

return 40

else:

raise AttributeError,attrname

执行结果

>>> X = empty()

>>> X.age

40

>>> X.name

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

  File "number.py", line 6, in __getattr__

    raise AttributeError,attrname

AttributeError: name

__setattr__样例:

class accesscontrol:

def __setattr__(self,attr,value):

if attr == 'age':

self.__dict__[attr] = value

else:

raise AttributeError,attr + 'not allowed'

执行结果:

>>> X = accesscontrol()

>>> X.age = 40

>>> X.age

40

>>> X.name = 'bob'

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

  File "number.py", line 6, in __setattr__

    raise AttributeError,attr + 'not allowed'

AttributeError: namenot allowed

【__call__拦截调用】

当实例调用时,使用__call__方法。

能够让实例的外观和使用方法类似于函数。

class Prod:

def __init__(self,value):

self.value = value





def __call__(self,other):

return self.value * other

>>> X = Prod(2)

>>> X(3)

6

以下的样例也能提供类似功能:

class Prod:

def __init__(self,value):

self.value = value





def comp(self,other):

return self.value * other

Python 点滴 IV的更多相关文章

  1. Python计算IV值

    更多大数据分析.建模等内容请关注公众号<bigdatamodeling> 在对变量分箱后,需要计算变量的重要性,IV是评估变量区分度或重要性的统计量之一,python计算IV值的代码如下: ...

  2. Python点滴记录-day-01

    python基础 - 基础 1.第一句python - 后缀名是可以可任意? - 导入模块时,如果不是.py文件 ==>以后文件后缀名是.py 2.两种执行方式 python解释器 py文件路径 ...

  3. 【Python】Python点滴(一)——pip工具使用

    首先我们来看一条命令:pip install uwsgi 这条命令按照操作名称,可以分为三个部分:pip.install和uwsgi.接下来,按照这样三个部分进行分析.   pip pip类似于Rea ...

  4. Python 点滴 I

    [为什么使用Python] 1. 软件质量:   Python更注重软件质量,一致性,可维护性 2. 开发效率:   相比C/C++/Java这些编译/静态语言,无需编译及链接步骤,Python所须要 ...

  5. python点滴:读取和整合文件夹下的所有文件

    当我们想读取一个文件夹下的多个文件,并且将所有文件的内容整合成一个文件,应该怎么做? 基本的思路是:写一个专门的函数实现以上两个功能.主要用到的命令包括os.listdir().codecs.open ...

  6. python点滴:判断字符串是否为合法json格式

    在一些情况下,我们需要判断字符串是否为合法json格式. 思路很简单:尝试对字符串使用json.loads(),如果不是合法json格式,则会抛出ValueError异常. 示例如下: import ...

  7. QuantStart量化交易文集

    Over the last seven years more than 200 quantitative finance articles have been written by members o ...

  8. OnePy--构建属于自己的量化回测框架

    本文主要记录我构建量化回测系统的学习历程. 被遗弃的项目:Chandlercjy/OnePy_Old 新更新中的项目:Chandlercjy/OnePy 目录 1. 那究竟应该学习哪种编程语言比较好呢 ...

  9. 基于linux运用python开发知识点滴

    我是小白,希望我的文章能对小白们有点作用. A.Linux的开源,优势明显,如何使用,基本命令如下: 个人认为最基础的两种操作: 1.文件操作: ls 看文件夹下内容 ls -a 隐藏文件 -l非隐藏 ...

随机推荐

  1. instanceof 原理

    运行流程 function instance_of(L, R) {                               //L 表示左表达式,R 表示右表达式   var O = R.prot ...

  2. 开发中关于Git那些事

    如果你想精通Git,直接到 Git官网 把这本ProGit掌握已足以Pro Git 此文主要介绍一切开发中常用的git命令和一些配置技巧(诸如git别名配置,log打印技巧,版本回退以及分支管理等). ...

  3. phpstudy APACHE支持.htaccess以及 No input file specified解决方案

    APACHE支持.htaccess以及 No input file specified解决方案 你的Apache安装文件夹conf里找到httpd.conf文件 索LoadModule rewrite ...

  4. Vue.js优雅的实现列表清单的操作

        一.Vue.js简要说明 Vue.js (读音 /vjuː/,类似于 view) 是一套构建用户界面的渐进式框架.与前端框架Angular一样, Vue.js在设计上采用MVVM模式,当Vie ...

  5. Maven 编译错误 Dynamic Web Module 3.0 requires Java 1.6 or newer 解决方案

    Eclipse Maven 开发一个 jee 项目时,编译时遇到以下错误:Description Resource Path Location TypeDynamic Web Module 3.0 r ...

  6. solr索引库的创建

    solr索引库的创建 一.找到你安装的[solrhome]目录(我的是这个) 二.进入该目录 三.选择其中任意一个索引库复制一份到该目录下并更名为要创建的索引库名称 四.进入[myindex]目录下, ...

  7. Python PycURL 网络编程

    http://blog.chinaunix.net/uid-20544356-id-290882.html 在使用urllib的时候经常会死掉,以前debug过,是没有设置 timing out 所以 ...

  8. CSharpGL(47)你好,Framebuffer!

    CSharpGL(47)你好,Framebuffer! Framebuffer对象(FBO)是一种复杂的OpenGL对象.使用自定义的framebuffer,可以实现离屏渲染,进而实现很多高级功能,例 ...

  9. MongoDB中聚合工具Aggregate等的介绍与使用

    Aggregate是MongoDB提供的众多工具中的比较重要的一个,类似于SQL语句中的GROUP BY.聚合工具可以让开发人员直接使用MongoDB原生的命令操作数据库中的数据,并且按照要求进行聚合 ...

  10. git log 中文乱码问题(浪费了一天)

    git log和gitcommit中文出现乱码,花了大半天的时间试了网上的各种方法,还是搞不定. 只好放大招. 卸载软件后重装,还没有进行任何配置,git config --list 发现有大量的配置 ...