很有一段时间没使用python了,前两天研究微信公众号使用了下python的django服务,感觉好多知识都遗忘了,毕竟之前没有深入的实践,长期不使用就忘得快。本博的主要目的就是对Python中我认为重要的面对对象知识进行总结,一是加深记忆,而是方便日后遗忘了好迅速的捡起来。

  目录索引:

  (1)隐式的基类object

  (2)python中类和对象的区别

  (3)实现python风格类所用特殊方法

    (a)__all__和__slots__

    (b)__format__()、__repr__()和__str__()

    (c)__init__()方法

    (d)__new__()和__del__()

    (e)__call__()方法

    (f)属性访问、特性和修饰符

    (g)@classmethod和@staticmethod

    (h)关于私有属性的说法

  (4)抽象基类和继承

1. 隐式的基类object

  每个Python类的定义都回隐式继承自object类,它的定义非常简单,几乎什么行为都不包括。

  

  可以看到类定义就是对type类的一个对象的类型声明,基类为object,相应的派生自object类中的对象方法也将继承各自相应的默认实现,在某些情况下,基类中一些特殊方法的默认行为也正是我们想要的,对于一些特殊情况,就需要重写这些方法。

  Python2 没有默认继承object

  Python3 默认全部继承object类,都是新式类

2. Python中类和对象的区别

(1)类属性和对象属性的区别

  对象可以通过 对象名.属性名 调用对象属性和类属性

  类可以通过 类名.属性名 调用类的属性,但是不能调用对象的属性

class People(object):
# 类属性是指定义在类的内部而且在方法的外部的属性
money =
def __init__(self,name,age,gender=):
# 对象属性是指定义在方法的内部的属性,例如本例中
# name,age和gender都是对象属性
self.name = name
self.age = age
self.gender = gender student1 = People("张三",)
student2 = People("李四",) print(student2.name)
print(student2.money)
print(People.money)
print(People.name)

  再注意看下面代码输出结果:

print(id(student1.money))
print(id(student2.money))
print(id(People.money))

  说明:对象student1、student2和类People的属性money的内存地址都是相同的

  继续往下看

student1.money -= 1000
print("student1.money:", student1.money)
print("student1.money id:",id(student1.money))
print("student2.money:", student2.money)
print("student2.money id:",id(student2.money))
print("People.money id:",id(People.money))

  说明:student1引用的money属性的内存地址已经和另外两个的不一样了而另外两个的内存地址却还是一样的

  原因:在经过表达式student1.money -= 1000 的过程时,会先在对象中查找是否有money这个属性,如果有的话,则直接进行运算如果没有,则会去类中查找是否有money属性,如果在类中找到money属性,那么student1就会创建一个对象属性money,在第二次调用的时候就会调用自己的对象属性,而不是类People中的属性了,而student2因为没有经过运算,所以不会创建自己的money属性,而是引用类People的属性,所以student2和People引用的还是同一个属性

3. 实现python风格类所用特殊方法

(a)__all__和__slots__

  关于__all__ = []总结两点:

  A:在__init__.py文件中 

表示形式:
__all__=["module_a","module_b"]
在使用 from package_name import * 时 , 表示import 该package 中的 两个module及 两个module相关的类、方法等。

  B:在普通的*.py中

表示形式:
__all__=["class_name","function_name"]
在使用 from module_name import * 时,表示import 该module中的__all__中所列出的。

  __slots__使用:

  如果我们想限制一个类的属性怎么办?比如只允许对Student实例添加name和age属性,为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量来限制class能添加的属性

>>> class Student(object):
... __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
... >>> s = Student() # 创建新的实例
>>> s.name = 'Michael' # 绑定属性'name'
>>> s.age = # 绑定属性'age'
>>> s.score = # 绑定属性'score'
Traceback (most recent call last):
File "<stdin>", line , in <module>
AttributeError: 'Student' object has no attribute 'score'

  由于score没有被放到__slots__中,所以不能绑定score属性,试图绑定score将得到AttributeError错误

  注意:__slots__定义的属性仅对当前类起作用,对继承的子类是不起作用的 

>>> class GraduateStudent(Student):
... pass
...
>>> g = GraduateStudent()
>>> g.score =

  除非在子类中也定义__slots__,这样子类允许定义的属性就是自身的__slots__加上父类的__slots__

(b)__format__()、__repr__()和__str__()

  上面的三个方法都是为了为Python对象提供一个很好的字符串表示

  通常str()方法表示的对象对用户更加友好,这个方法由__str__()实现

  repr()方法的表示通常会被更加技术化,这个方法由__repr__()实现

  {!r} 调用__repr__方法

  {!s} 调用__str__方法

  string.format()和内置的format()函数都使用__format()__方法,都是为了获得给定对象的一个符合要求的字符串表示

  直接上例子能更好的进行说明:

class People:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex def __str__(self):
#return "{__class__.__name__}(name={0},age={1},sex={2})" .format(self.name,self.age,self.sex,__class__=self.__class__)
return "__str__:(name={name},age={age},sex={sex})" .format(__class__=self.__class__,**self.__dict__) def __repr__(self):
return "__repr__:{__class__.__name__}(name={name},age={age},sex={sex})" .format(__class__=self.__class__,**self.__dict__) def __format__(self, format_spec):
if format_spec == "":
return str(self)
return format_spec.replace("%n",self.name).replace("%s",self.sex) if __name__ == "__main__":
people = People("john",,"man")
print("{0!s}".format(people))
print("{0!r}".format(people))
print("format:",format(people,"%n-%s"))
print("__format__:",people.__format__("%n-%s"))
print("format:",format(people))

(c)__init__()方法

  __init__(self)就如同类的构造函数,尽量在构造函数中实现属性清单,这里就不多做介绍

  下面主要总结下Python继承中super()方法的使用:

  super实现原理:通过c3算法,生成mro(method resolution order)列表,根据列表中元素顺序查询调用新式类调用顺序为广度优先,旧式类为深度优先
  super类似于嵌套的一种设计,当代码执行到super实例化后,先去找同级父类,若没有其余父类,再执行自身父类,再往下走,简单说就是子类在父类前,所有类不重复调用,从左到右(见下面例子的D.mro()打印)

  Python2 super调用 super(开始类名,self).函数名()

  Python3  super().函数名()

  上例子更能说明上述问题:

class A():
def go(self):
print ("go A go!")
def stop(self):
print ("stop A stop!")
def pause(self):
raise Exception("Not Implemented")
class B(A):
def go(self):
super(B, self).go()
print ("go B go!")
class C(A):
def go(self):
super(C, self).go()
print ("go C go!")
def stop(self):
super(C, self).stop()
print ("stop C stop!")
class D(B,C):
def go(self):
super(D, self).go()
print ("go D go!")
def stop(self):
super(D, self).stop()
print ("stop D stop!")
def pause(self):
print ("wait D wait!")
class E(B,C):
pass a = A()
b = B()
c = C()
d = D()
e = E()
# 说明下列代码的输出结果
d.go()
print('--------')
e.go()
print('--------')
d.stop()
print('--------')
e.stop()
print(D.mro())
a.pause()
b.pause()
c.pause()
d.pause()
e.pause()

(d)__new__()和__del__()

  __ new__ ()在__ init__()之前被调用,用于生成实例对象.利用这个方法和类属性的特性可以实现设计模式中的单例模式.单例模式是指创建唯一对象吗,单例模式设计的类只能实例化一个对象.

class Singleton(object):
__instance = None # 定义实例 def __init__(self):
pass def __new__(cls, *args, **kwd): # 在__init__之前调用
if Singleton.__instance is None: # 生成唯一实例
Singleton.__instance = object.__new__(cls, *args, **kwd)
return Singleton.__instance

  __new__()方法的使用和Python元编程相关,可以查看我之前的博客:Python元编程

  __del__()方法涉及到Python对象销毁,Python文档中用不稳定性来描述__del__()方法的这种行为,并且提供了额外的关于异常处理的注释,总之,该函数的使用要慎重之慎重。

  __ del__称作析构方法
  析构方法,当对象在内存中被释放时,自动触发执行。
  注:此方法一般无须定义,因为在Python中,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。在程序执行结束之后,执行此方法

(e)__call__()方法

  Python可调用对象:函数,方法,使用 yield 关键字的函数或方法,类的实例

  __call__方法将类的实例变成可调用对象

>>>class Reader():
    def __init__(self,name,nationality):
      self.name = name
      self.nationality = nationality
    def __call__(self):
      print('Reader: %s Nationality: %s' % (self.name, self.nationality))
>>>r = Reader('Annie','Chinese')
>>>r()
Reader:Annie Nationality: Chinese

(f)属性访问、特性和修饰符

  之前的博客Python之属性、特性和修饰符作了详细说明

(g)@classmethod和@staticmethod

  classmethod 修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。

#!/usr/bin/python
# -*- coding: UTF- -*- class A(object):
bar =
def func1(self):
print ('foo')
@classmethod
def func2(cls):
print ('func2')
print (cls.bar)
cls().func1() # 调用 foo 方法 A.func2() # 不需要实例化

  staticmethod修饰符实现静态方法,该方法不强制要求传递参数

#!/usr/bin/python
# -*- coding: UTF- -*- class C(object):
@staticmethod
def f():
print('runoob'); C.f(); # 静态方法无需实例化
cobj = C()
cobj.f() # 也可以实例化后调用

(h)关于私有属性的说法

  Python并没有真正的私有化支持,但可用下划线得到伪私有

  个人习惯:

  (1)_XXX 单下划代表protected

  (2)__XXX 双下划线开始的且不以_结尾表示private(下面说明)

  (3)__XXX__系统定义的属性和方法

  看下面的例子:

class People:
__name="zhanglin" def __init__(self):
self.__age = print(People.__dict__)
p = People()
print(p.__dict__)

  会发现__name和__age属性名都发生了变化,都变成了(_类名+属性名),只有在__XXX这种命名方式下才会发生变化,所以以这种方式作为伪私有说明

4. 抽象基类和继承

  该主题内容请查看之前的博客:Python之抽象基类

Python面对对象相关知识总结的更多相关文章

  1. Python - 面对对象(其他相关,异常处理,反射,单例模式,等..)

    目录 Python - 面对对象(其他相关,异常处理,反射,等..) 一.isinstance(obj, cls) 二.issubclass(sub, super) 三.异常处理 1. 异常处理 2. ...

  2. Python - 面对对象(基础)

    目录 Python - 面对对象(基础) 一. 概述 二. 创建类和对象 三. 面向对象三大特征 封装 继承 多态 Python - 面对对象(基础) 一. 概述 面向过程:根据业务逻辑从上到下写垒代 ...

  3. Python - 面对对象(进阶)

    目录 Python - 面对对象(进阶) 类的成员 一. 字段 二. 方法 三. 属性 类的修饰符 类的特殊成员 Python - 面对对象(进阶) 类的成员 一. 字段 字段包括:普通字段和静态字段 ...

  4. 小学生绞尽脑汁也学不会的python(面对对象-----类与类之间的关系)

    小学生绞尽脑汁也学不会的python(面对对象-----类与类之间的关系 1. 依赖关系. 最轻的一种关系 在方法中引入另一个类的对象 class Elephant: def __init__(sel ...

  5. 小学生绞尽脑汁也学不会的python(面对对象-----成员)

    小学生绞尽脑汁也学不会的python(面对对象-----成员) 成员 class Person: def __init__(self, name, num, gender, birthday): # ...

  6. 16、python面对对象之类和继承

    前言:本文主要介绍python面对对象中的类和继承,包括类方法.静态方法.只读属性.继承等. 一.类方法 1.类方法定义 使用装饰器@classmethod装饰,且第一个参数必须是当前类对象,该参数名 ...

  7. 15、python面对对象之类和对象

    前言:本文主要介绍python面对对象中的类和对象,包括类和对象的概念.类的定义.类属性.实例属性及实例方法等. 一.类和对象的概念 问题:什么是类?什么是实例对象? 类:是一类事物的抽象概念,不是真 ...

  8. python面对对象编程------4:类基本的特殊方法__str__,__repr__,__hash__,__new__,__bool__,6大比较方法

    一:string相关:__str__(),__repr__(),__format__() str方法更面向人类阅读,print()使用的就是str repr方法更面对python,目标是希望生成一个放 ...

  9. python面对对象编程----2:__init__

    面对对象编程估计我们最早接触到的就是__init__了,也就是实例的初始化处理过程: 1:来看看最基础的__init__ class Card(object): #抽象类Card,并不用于实例化 de ...

随机推荐

  1. Java基础_基本语法

    Java基本语法 一:关键字 在Java中有特殊含义的单词(50). 二:标志符 类名,函数名,变量名的名字的统称. 命名规则: 可以是字母,数字,下划线,$. 不能以数字开头. 见名之意. 驼峰规则 ...

  2. C# int32与int64的区别 附加:字符字节关系

    int32 =int int64 =long 1byte=8bit unicode 占2btye int32 占 1 btye long 占 4 btye

  3. 什么是MSB/LSB码?

    MSB是Most Significant Bit的缩写,最高有效位.在二进制数中,MSB是最高加权位.与十进制数字中最左边的一位类似.通常,MSB位于二进制数的最左侧,LSB位于二进制数的最右侧. L ...

  4. windows技巧--一次关闭所有资源管理器目录,文件夹目录

    每天开机工作一段时间以后,你可能会和我一样,打开了很多的文件目录,于是一个一个的点窗口关闭.于是想有没有一次关闭所有目录的办法~~咚咚咚,经过一番寻觅,下面是我找到的办法 新建bat文件 close_ ...

  5. Asp.net Core, 基于 claims 实现权限验证 - 引导篇

    什么是Claims? 这个直接阅读其他大神些的文章吧,解释得更好. 相关文章阅读: http://www.cnblogs.com/JustRun1983/p/4708176.html http://w ...

  6. java基础(5)--流程控制结构

    流程控制结构 if结构 当关系表达式为true时,执行语句 if(关系表达式){ //语句块 } if-else结构 当关系表达式为true时,执行语句块1,否则执行语句块2 if(关系表达式){ / ...

  7. Gym - 101503I 利用到图论的构造

    比赛的时候没有注意到 给出的up矩阵 能使我们随便选一列 确定这一列的rank 这样我们得出每一行列的rank 进行构图 大->小 然后从大到小放 当前放的点 和他有因果关系并且比他大的点必须已 ...

  8. TrappingRainWater

    问题描述: Given n non-negative integers representing an elevation map where the width of each bar is 1, ...

  9. 画龙点睛 之RabbitMQ 初来乍到

    消息队列解决了什么问题 1. 异步处理 2. 应用解耦 3. 流量削峰 4. 日志处理...... 安装RabbitMQ (这里的安装我只仅仅说一下linux 的安装 如果想安装windows 版 可 ...

  10. spring3: 基于Schema的AOP

    6.3  基于Schema的AOP 基于Schema的AOP从Spring2.0之后通过“aop”命名空间来定义切面.切入点及声明通知. 在Spring配置文件中,所以AOP相关定义必须放在<a ...