目录:

1       面向对象编程
1.1    简单例子
1.2    调用
1.3    python命名规范(约定)
1.4    类的设计
1.4.1 Exception 异常捕获结构
1.4.2 自定义异常
1.4.3 __init__.
1.4.4 __new__.
1.4.5 __new__ 的作用
1.4.6 用__new__来实现单例
1.4.7 静态方法
1.4.8 类方法
1.5    面向对象编程
1.5.1 Python支持多继承
1.5.2 多态 (override overload)
1.6    super关键字
1.6.1 普通继承
1.6.2 super继承

 

 

 

1       面向对象编程

1.1   简单例子

#!/usr/bin/python

#-*- encoding:utf-8 -*-

class test: #定义一个test

    desc = "这是一个测试类。" #在类中定义一个属性desc

    def __init__(self,name1): #对象构造函数,初始化类

        self.name1 = name1

    def show(self,name2): #在类中定义一个方法show()

        print("hello world")

        print('name1:',self.name1)

        print('name2:',name2)

 

1.2   调用

obj = test('这是传递给name1的值') #生成test类的实例对象

print(obj.desc) #调用类中的desc属性

obj.show('这是传递给name2的值') #调用类中的show()方法  

 

1.3   python命名规范(约定)

类里面 “单下划线” 开始的成员变量叫做保护变量,  意思是只有类对象和子类对象自己能访问到这些变量;

而 "双下划线" 开始的是私有成员, 意思是只有类对象自己能访问, 连子类对象也不能访问到这个数据。

类的首字母大写, 没有特别原因不要在前面加 “T或者 “C什么的

函数和变量尽量全小写, 单词间用下划线连接。

 

 

1.4   类的设计

 class Foo:

      def __init__(self, a, b):

        self.a = a

        self.b = b

      def show_a(self):

        print self.a

      def show_b(self):

        print self.b

    __init__ 函数:每次生成类的时候都会执行的, self 指向类对象自身。

记住, 类函数(或者叫做方法) 它的第一个参数 “self不要忘记写了

其中的“__del__”就是一个析构函数了,当使用del 删除对象时,会调用他本身的析构函数,另外当对象在某个作用域中调用完毕,在跳出其作用域的同时析构函数也会被调用一次,这样可以用来释放内存空间。

       foo_obj = Foo("I'm A", "I'm B")

     foo_obj.show_a()

     foo_obj.b = "Hello world!"

     foo_obj.show_b()

1.4.1   Exception  异常捕获结构

try:

……

except Exceptionname

…….

except:

       …….

else:

       …….

finally:

       …….

1.4.2   自定义异常

       class MyError(Exception):

              pass

       raise 关键字 可以抛出自定义的异常

              例: raise MyError

注意:一定注意先后顺序, 要先定义异常类后才可以使用, 而不能上来就用。

1.4.3   __init__

 

程序cPerson.py

class Person(object):

    """Silly Person"""

 

    def __init__(self, name, age):

        self.name = name

        self.age = age

 

 

    def __str__(self):

        return '<Person: %s(%s)>' % (self.name, self.age)

 

 

if __name__ == '__main__':

    piglei = Person('piglei', 24)

print piglei

运行:

>>> import cPerson

>>> str(a)

'<Person: yong(22)>'

>>> a=cPerson.Person('LiLee',22)

>>> str(a)

'<Person: LiLee(22)>'

 

1.4.4   __new__

每一个 new-style class 都有一个名为{{_new_}}的静态方法. 当你调用 C(args,kwds)创建一个C实例时,python内部调用的是 C._new_(C,*args,*kwds).

{_new_}}方法的返回值 x 就是该类的实例. 在确认 x 是C的实例以后, python调用C.{{_init_(x,args,*kwds)来初始化这个实例. 也就是说,对新类C来讲,语句 x=C(23)等同于

x = C._new_(C, 23)

if isinstance(x, C): C._init_(x, 23)

_new方法拥有函数工厂的绝大部分弹性. 根据实际需求,我们可以让new_返回一个已有的实例或者创建一个新的实例.

下面举一个通过重载_new_方法实现独身对象的设计模式的例子:

class Singleton(object):

 _singletons = {}
 def _new_(cls, *args, **kwds):
 if not cls._singletons.has_key(cls): #
若还没有任何实例
      cls.singletonscls
= object.new_(cls) #
生成一个实例
 return cls._singletonscls #
返回这个实例
Singleton
的所有子类(当然是没有重载_new方法的子类)都只可能有一个实例. 如果该类的子类定义了一个init方法,那么它必须保证它的init_方法能够安全的对同一实例进行多次调用.

 

__new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而
__new__
方法正是创建这个类实例的方法。 

# -*- coding:
utf-8 -*-

class Person(object):

    """Silly
Person"""

 

 

    def __new__(cls, name, age):

        print '__new__ called.'

        return super(Person, cls).__new__(cls,
name, age)

 

 

    def __init__(self, name, age):

        print '__init__ called.'

        self.name = name

        self.age = age

 

 

    def __str__(self):

        return '<Person: %s(%s)>' %
(self.name, self.age)

 

 

if __name__ ==
'__main__':

    piglei = Person('piglei', 24)

    print piglei

执行结果:

执行方法1

$ python new_and_init.py

__new__ called.

__init__ called.

<Person: piglei(24)>

执行方法2:

>>> 

>>>
import cPerson

>>>
a=Person('dd',39)

__new__
called.

__init__
called.

通过运行这段代码,我们可以看到,__new__方法的调用是发生在__init__之前的。其实当你实例化一个类的时候,具体的执行逻辑是这样的:

  • p = Person(name, age)
  • 首先执行使用nameage参数来执行Person类的__new__方法,这个__new__方法会返回Person类的一个实例(通常情况下是使用 super(Persion,
    cls).__new__(cls, ... ...)
    这样的方式),
  • 然后利用这个实例来调用类的__init__方法,上一步里面__new__产生的实例也就是 __init__里面的的 self

所以,__init__ __new__ 最主要的区别在于: 

  • __init__ 通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性,做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。
  • __new__ 通常用于控制生成一个新实例的过程。它是类级别的方法。

 

参考:

http://my.oschina.net/leejun2005/blog/207371

1.4.5  
__new__ 的作用

依照Python官方文档的说法,__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple)提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass

首先我们来看一下第一个功能,具体我们可以用int来作为一个例子:

假如我们需要一个永远都是正数的整数类型,通过集成int,我们可能会写出这样的代码。

 

class PositiveInteger(int):

    def __init__(self, value):

        super(PositiveInteger,
self).__init__(self, abs(value))

i =
PositiveInteger(-3)

print
i

但运行后会发现,结果根本不是我们想的那样,我们任然得到了-3。这是因为对于int这种 不可变的对象,我们只有重载它的__new__方法才能起到自定义的作用。

这是修改后的代码:

class
PositiveInteger(int):

    def __new__(cls, value):

        return super(PositiveInteger,
cls).__new__(cls, abs(value))

i =
PositiveInteger(-3)

print
i

通过重载__new__方法,我们实现了需要的功能。

另外一个作用,关于自定义metaclass。其实我最早接触__new__的时候,就是因为需要自定义 metaclass,但鉴于篇幅原因,我们下次再来讲python中的metaclass和__new__的关系。

1.4.6  
用__new__来实现单例

事实上,当我们理解了__new__方法后,我们还可以利用它来做一些其他有趣的事情,比如实现
设计模式中的
单例模式(singleton)

因为类每一次实例化后产生的过程都是通过__new__来控制的,所以通过重载__new__方法,我们可以很简单的实现单例模式。

class
Singleton(object):

    def __new__(cls):

        # 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象

        if not hasattr(cls, 'instance'):

            cls.instance = super(Singleton,
cls).__new__(cls)

        return cls.instance

obj1 = Singleton()

obj2
= Singleton()

 

obj1.attr1
= 'value1'

print
obj1.attr1, obj2.attr1

print
obj1 is obj2

输出结果:

value1
value1

True

可以看到obj1和obj2是同一个实例。

class
Singleton(object):

    __instance = None

    def __init__(self, *args, **kwargs):

        pass

    def __new__(cls, *args, **kwargs):

        if not cls.__instance:

            # if not hasattr(cls, 'instance'):

            cls.__instance = super(Singleton,
cls).__new__(cls, *args, **kwargs)

            cls.__instance.aa = args[0]

            print type(cls),
type(cls.__instance), type(cls.__instance.aa)

        return cls.__instance

 

obj1
= Singleton(1, 2, 3, b=2)

obj2
= Singleton(1, 2, 3, b=2)

 

obj1.attr1
= 'value1'

obj2.attr2
= 'value2'

print
obj1.attr1, obj1.attr2

print
obj1 is obj2

print
obj1.aa, obj2.attr1

 

 

结果:

<type
'type'> <class '__main__.Singleton'> <type 'int'>

value1
value2

True

1
value1

 

1.4.7  
静态方法

 @staticmethod
#
静态方法修饰符,表示下面的方法是一个静态方法

 def astatic( ): print 'a static method'
 anInstance = AClass( )
 AClass.astatic( ) # prints: a static
method
 anInstance.astatic( ) # prints: a static
method

1.4.8  
类方法

@classmethod #类方法修饰符

 def aclassmet(cls): print 'a class method
for', cls._name_
 class ADeriv(ABase): pass

 bInstance = ABase( )
 dInstance = ADeriv( )
 ABase.aclassmet( ) # prints: a class
method for ABase
 bInstance.aclassmet( ) # prints: a class
method for ABase
 ADeriv.aclassmet( ) # prints: a class
method for ADeriv
 dInstance.aclassmet( ) # prints: a class
method for ADeriv

1.5  
面向对象编程

前面提到的操作函数和语句块是传统的面向过程编程,而编写大型程序,通常采用面向对象编程。类和对象是面向对象编程的两个主要方面,类创建一个新类型,而对象是类的实例。Python没有什么值类型与引用类型之分,它把所有事物统统看作是类。

面向对象实质上是一种思想,并不是一门技术。面向对象讲求一切皆对象.

面向对象的三大特性

继承

封装

多态

为什么要面向对象?

灵活性, 重用性。

继承关系可以被传递,如果c1是c2的子类,c2是c3的子类,那么c1也是c3的子类。

如果a继承b那么a具有b的一切属性和方法。

1.5.1  
Python支持多继承

class
A:

    def __init__(self):

        pass

class
B:

    def __init__(self):

        pass

class
C(A,B):

    def __init__(self):

        pass

    sex=''

    def Say(self):

        print self.name+ self.sex+self.age

1.5.2  
多态  (override  overload)

Python
中的多态并没有完全实现,Python中只是利用多元化来实现部分多态的特性

class Person:   

    def __init__(self,name):

        self.Name=name

    Name='name'

    Sex='man'

    Age='age'

    def Say(self,message):

        print self.Name+message

class Role(Person):

    def __init__(self,name,roleName):

        Person.__init__(self,name)

        self.RoleName=roleName

    RoleName='roleName'#  light or dark

    def
Say(self,message):

        print self.RoleName+self.Name+message

1.6  
super关键字

super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。

总之前人留下的经验就是:保持一致性。要不全部用类名调用父类,要不就全部用
super
,不要一半一半。

 

1.6.1  
普通继承

代码:

[python]view
plaincopy
在CODE上查看代码片派生到我的代码片

class
FooParent(object): 

    def __init__(self): 

        self.parent = 'I\'m the parent.' 

        print 'Parent' 

     

    def bar(self,message): 

        print message, 'from Parent' 

         

class
FooChild(FooParent): 

    def __init__(self): 

        FooParent.__init__(self) 

        print 'Child' 

         

    def bar(self,message): 

        FooParent.bar(self,message) 

        print 'Child bar function.' 

        print self.parent 

         

if
__name__=='__main__': 

    fooChild = FooChild() 

    fooChild.bar('HelloWorld') 

 

 

1.6.2  
super继承

代码

[python]view
plaincopy
在CODE上查看代码片派生到我的代码片

class
FooParent(object): 

    def __init__(self): 

        self.parent = 'I\'m the parent.' 

        print 'Parent' 

     

    def bar(self,message): 

        print message,'from Parent' 

 

class
FooChild(FooParent): 

    def __init__(self): 

        super(FooChild,self).__init__() 

        print 'Child' 

         

    def bar(self,message): 

        super(FooChild, self).bar(message) 

        print 'Child bar fuction' 

        print self.parent 

 

if
__name__ == '__main__': 

    fooChild = FooChild() 

    fooChild.bar('HelloWorld') 

 

程序运行结果相同,为:

Parent

Child

HelloWorld
from Parent

Child
bar fuction

I'm
the parent.

 

从运行结果上看,普通继承和super继承是一样的。但是其实它们的内部运行机制不一样,这一点在多重继承时体现得很明显。在super机制里可以保证公共父类仅被执行一次,至于执行的顺序,是按照mro进行的(E.__mro__)。

 

注意:super继承只能用于新式类,用于经典类时就会报错。

新式类:必须有继承的类,如果没什么想继承的,那就继承object

经典类:没有父类,如果此时调用super就会出现错误:

super()
argument 1 must be type, not classobj

 

 

1.7  
python的cls,self,classmethod,staticmethod

python类里会出现这三个单词,self和cls都可以用别的单词代替,类的方法有三种,

1.通过def定义的 普通的一般的,需要至少传递一个参数,一般用self,这样的方法必须通过一个类的实例去访问,类似于c++中通过对象去访问;
2.在def前面加上@classmethod,这种类方法的一个特点就是可以通过类名去调用,但是也必须传递一个参数,一般用cls表示class,表示可以通过类直接调用;
3.在def前面加上@staticmethod,这种类方法是静态的类方法,类似于c++的静态函数,他的一个特点是参数可以为空,同样支持类名和对象两种调用方式;

 

class
A:

    member = "this is a test."

    def __init__(self):

        pass

 

    @classmethod

    def Print1(cls):

        print "print 1: ", cls.member

       

    def Print2(self):

        print "print 2: ",
self.member

          

       

    @classmethod   

    def Print3(paraTest):

        print "print 3: ",
paraTest.member

    @staticmethod

    def print4():

        print "hello"

   

 

a =
A()

A.Print1() 

a.Print1()

#A.Print2()

a.Print2()

A.Print3()

a.Print3()

A.print4()

1.8  
pythonself,cls

普通的方法,第一个参数需要是self,它表示一个具体的实例本身。

如果用了staticmethod,那么就可以无视这个self,而将这个方法当成一个普通的函数使用。

而对于classmethod,它的第一个参数不是self,是cls,它表示这个类本身。

>>>
class A(object):

    def foo1(self):

        print "Hello",self

    @staticmethod

    def foo2():

        print "hello"

    @classmethod

    def foo3(cls):

        print "hello",cls

 

       

>>>
a = A()

>>>
a.foo1()          #
最常见的调用方式,但与下面的方式相同

Hello
<__main__.A object at 0x9f6abec>

>>>
A.foo1(a)         #
这里传入实例a,相当于普通方法的self

Hello
<__main__.A object at 0x9f6abec>

>>>
A.foo2()          #
这里,由于静态方法没有参数,故可以不传东西

hello

>>>
A.foo3()          #
这里,由于是类方法,因此,它的第一个参数为类本身。

hello
<class '__main__.A'>

>>>
A                 #
可以看到,直接输入A,与上面那种调用返回同样的信息。

<class
'__main__.A'>

 

 

1.8.1   其他例子

cls是class的缩写。

class
A:

    member = "this is a test."

    def __init__(self):

        pass

 

    @classmethod

    def Print1(cls):

        #

        print "print 1: ", cls.member

        

    def Print2(self):

        print "print 2: ",
self.member

           

        

    @classmethod   

    def Print3(paraTest):

        print "print 3: ",
paraTest.member

 

a =
A()

A.Print1()   #相当于Print1(A)

a.Print2()   #相当于Print2(a)请注意@classmethod

A.Print3()  

 

 

可以看出来,python在通过“.”调用成员函数的时候,会将“.”前面的东西当作函数的第一个参数调用。

而且pyhon并不关心我们把类的成员函数的第一个参数的名称是什么,我们可以用任意的名称,可以看Print3的定义就知道了。

Python_09-面向对象编程的更多相关文章

  1. angular2系列教程(六)两种pipe:函数式编程与面向对象编程

    今天,我们要讲的是angualr2的pipe这个知识点. 例子

  2. 带你一分钟理解闭包--js面向对象编程

    上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...

  3. PHP 面向对象编程和设计模式 (1/5) - 抽象类、对象接口、instanceof 和契约式编程

    PHP高级程序设计 学习笔记 2014.06.09 什么是面向对象编程 面向对象编程(Object Oriented Programming,OOP)是一种计算机编程架构.OOP 的一条基本原则是计算 ...

  4. Delphi_09_Delphi_Object_Pascal_面向对象编程

    今天这里讨论一下Delphi中的面向对象编程,这里不做过多过细的讨论,主要做提纲挈领的描述,帮助自己抓做重点. 本随笔分为两部分: 一.面向对象编程 二.面向对象编程详细描述 ------------ ...

  5. python基础-面向对象编程

    一.三大编程范式 编程范式即编程的方法论,标识一种编程风格 三大编程范式: 1.面向过程编程 2.函数式编程 3.面向对象编程 二.编程进化论 1.编程最开始就是无组织无结构,从简单控制流中按步写指令 ...

  6. 面向对象编程(OOP)

    什么是面向对象编程,对于面向对象编程与面向过程编程的解释随处可见,个人认为对面向对象编程解释最好的一个定义是:依赖倒转原则是面向对象编程的标志,面向对象编程是一种思想,无论使用哪一种编程语言,如果在编 ...

  7. python 学习笔记7 面向对象编程

    一.概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发"更快更好更强..." ...

  8. 进击的Python【第七章】:Python的高级应用(四)面向对象编程进阶

    Python的高级应用(三)面向对象编程进阶 本章学习要点: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 一.面向对象高级语法部分 静态方法 ...

  9. 进击的Python【第六章】:Python的高级应用(三)面向对象编程

    Python的高级应用(三)面向对象编程 本章学习要点: 面向对象编程介绍 面向对象与面向过程编程的区别 为什么要用面向对象编程思想 面向对象的相关概念 一.面向对象编程介绍 面向对象程序设计(英语: ...

  10. 第二章 Matlab面向对象编程基础

    DeepLab是一款基于Matlab面向对象编程的深度学习工具箱,所以了解Matlab面向对象编程的特点是必要的.笔者在做Matlab面向对象编程的时候发现无论是互联网上还是书店里卖的各式Matlab ...

随机推荐

  1. 洛谷 P3802 小魔女帕琪

    传送门 题目大意:7个东西,每个有ai个,只有选7次 把7个东西都选到了才行. 题解:7!排列数*每次选择的概率 代码: #include<iostream> #include<cs ...

  2. http接口测试工具

    2016-08-28 19:24:55 以全国天气预报为例  https://www.juhe.cn/docs/api/id/39/aid/132 (一)火狐的HttpRequester 在URL中填 ...

  3. cocos2dx调度器(scheduler)

    调度器(scheduler) http://cn.cocos2d-x.org/article/index?type=cocos2d-x&url=/doc/cocos-docs-master/m ...

  4. hadoop之 distcp(分布式拷贝)

    概述 distcp(分布式拷贝)是用于大规模集群内部和集群之间拷贝的工具. 它使用Map/Reduce实现文件分发,错误处理和恢复,以及报告生成. 它把文件和目录的列表作为map任务的输入,每个任务会 ...

  5. MVC涉及RouteTable自定义路径

    Routing 到目前为止,我们已经解决了MVC的很多问题,但忽略了最基本的最重要的一个问题:当用户发送请求时,会发生什么? 最好的答案是“执行Action 方法”,但仍存在疑问:对于一个特定的URL ...

  6. Linux下使用locale命令设置语言环境

    locale命令设置语言环境 在Linux中通过locale来设置程序运行的不同语言环境,locale由 ANSI C提供支持.locale的命名规则为_.,如zh_CN.GBK,zh代表中文, CN ...

  7. SmtpClient发送邮件

    使用第三方SMTP服务器来发送邮件.如网易: SmtpClient sc = new SmtpClient("smtp.126.com"); sc.Credentials = ne ...

  8. STM32启动过程解读与跟踪验证

    经过查阅各种官方文献和对代码进行单步跟踪,详细地叙述了STM32加电启动的具体过程.对于关键性的语句都指明了出处.下面将学习成果分享给大家,由于笔者知识有限,不当之处敬请指出. 为了更好的说明问题,先 ...

  9. Socket客户端

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...

  10. centos6.9 x64安装http,php5.6,curl5.29,mysql最后安装zabbix3.4+zabbix客户端

    https://www.zabbix.com/documentation/3.4/zh/manual/installation/requirementshttps://www.zabbix.com/d ...