Python_09-面向对象编程
目录:
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)
- 首先执行使用name和age参数来执行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
python中self,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-面向对象编程的更多相关文章
- angular2系列教程(六)两种pipe:函数式编程与面向对象编程
今天,我们要讲的是angualr2的pipe这个知识点. 例子
- 带你一分钟理解闭包--js面向对象编程
上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...
- PHP 面向对象编程和设计模式 (1/5) - 抽象类、对象接口、instanceof 和契约式编程
PHP高级程序设计 学习笔记 2014.06.09 什么是面向对象编程 面向对象编程(Object Oriented Programming,OOP)是一种计算机编程架构.OOP 的一条基本原则是计算 ...
- Delphi_09_Delphi_Object_Pascal_面向对象编程
今天这里讨论一下Delphi中的面向对象编程,这里不做过多过细的讨论,主要做提纲挈领的描述,帮助自己抓做重点. 本随笔分为两部分: 一.面向对象编程 二.面向对象编程详细描述 ------------ ...
- python基础-面向对象编程
一.三大编程范式 编程范式即编程的方法论,标识一种编程风格 三大编程范式: 1.面向过程编程 2.函数式编程 3.面向对象编程 二.编程进化论 1.编程最开始就是无组织无结构,从简单控制流中按步写指令 ...
- 面向对象编程(OOP)
什么是面向对象编程,对于面向对象编程与面向过程编程的解释随处可见,个人认为对面向对象编程解释最好的一个定义是:依赖倒转原则是面向对象编程的标志,面向对象编程是一种思想,无论使用哪一种编程语言,如果在编 ...
- python 学习笔记7 面向对象编程
一.概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发"更快更好更强..." ...
- 进击的Python【第七章】:Python的高级应用(四)面向对象编程进阶
Python的高级应用(三)面向对象编程进阶 本章学习要点: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 一.面向对象高级语法部分 静态方法 ...
- 进击的Python【第六章】:Python的高级应用(三)面向对象编程
Python的高级应用(三)面向对象编程 本章学习要点: 面向对象编程介绍 面向对象与面向过程编程的区别 为什么要用面向对象编程思想 面向对象的相关概念 一.面向对象编程介绍 面向对象程序设计(英语: ...
- 第二章 Matlab面向对象编程基础
DeepLab是一款基于Matlab面向对象编程的深度学习工具箱,所以了解Matlab面向对象编程的特点是必要的.笔者在做Matlab面向对象编程的时候发现无论是互联网上还是书店里卖的各式Matlab ...
随机推荐
- 洛谷 P3802 小魔女帕琪
传送门 题目大意:7个东西,每个有ai个,只有选7次 把7个东西都选到了才行. 题解:7!排列数*每次选择的概率 代码: #include<iostream> #include<cs ...
- http接口测试工具
2016-08-28 19:24:55 以全国天气预报为例 https://www.juhe.cn/docs/api/id/39/aid/132 (一)火狐的HttpRequester 在URL中填 ...
- cocos2dx调度器(scheduler)
调度器(scheduler) http://cn.cocos2d-x.org/article/index?type=cocos2d-x&url=/doc/cocos-docs-master/m ...
- hadoop之 distcp(分布式拷贝)
概述 distcp(分布式拷贝)是用于大规模集群内部和集群之间拷贝的工具. 它使用Map/Reduce实现文件分发,错误处理和恢复,以及报告生成. 它把文件和目录的列表作为map任务的输入,每个任务会 ...
- MVC涉及RouteTable自定义路径
Routing 到目前为止,我们已经解决了MVC的很多问题,但忽略了最基本的最重要的一个问题:当用户发送请求时,会发生什么? 最好的答案是“执行Action 方法”,但仍存在疑问:对于一个特定的URL ...
- Linux下使用locale命令设置语言环境
locale命令设置语言环境 在Linux中通过locale来设置程序运行的不同语言环境,locale由 ANSI C提供支持.locale的命名规则为_.,如zh_CN.GBK,zh代表中文, CN ...
- SmtpClient发送邮件
使用第三方SMTP服务器来发送邮件.如网易: SmtpClient sc = new SmtpClient("smtp.126.com"); sc.Credentials = ne ...
- STM32启动过程解读与跟踪验证
经过查阅各种官方文献和对代码进行单步跟踪,详细地叙述了STM32加电启动的具体过程.对于关键性的语句都指明了出处.下面将学习成果分享给大家,由于笔者知识有限,不当之处敬请指出. 为了更好的说明问题,先 ...
- Socket客户端
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...
- 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 ...