# ====================第八章:类与对象=========================

# --------------改变对象的字符串显示----------------------
# 要改变一个实例的字符串表示,可重新定义它的__str__() 和__repr__() 方法
class User:
def __init__(self, name, age):
self.name = name
self.age = age
# __repr__() 方法返回一个实例的代码表示形式,通常用来重新构造这个实例。
def __repr__(self):
return 'User({0.name}, {0.age})'.format(self)
# __str__() 方法将实例转换为一个字符串
def __str__(self):
return '({0.name}, {0.age})'.format(self)
# 如果__str__() 没有被定义,那么就会使用__repr__() 来代替输出 # --------------自定义字符串的格式化-----------------------
# 通过__format__() 函数和字符串方法使得一个对象能支持自定义的格式化 # ---------------让对象支持上下文管理-------------------------
# 为了让一个对象兼容with 语句,需要实现__enter__() 和__exit__() 方法
# 编写上下文管理器的主要原理是你的代码会放到with 语句块中执行
# 当出现with语句的时候,对象的__enter__() 方法被触发,
# 它返回的值(如果有的话) 会被赋值给as 声明的变量。
# 然后,with 语句块里面的代码开始执行。
# 最后,__exit__() 方法被触发进行清理工作。
"""
不管with 代码块中发生什么,上面的控制流都会执行完,就算代码块中发生了异
常也是一样的。事实上, exit () 方法的第三个参数包含了异常类型、异常值和追溯
信息(如果有的话)。exit () 方法能自己决定怎样利用这个异常信息,或者忽略它
并返回一个None 值。如果exit () 返回True ,那么异常会被清空,就好像什么都
没发生一样, with 语句后面的程序继续在正常执行。
""" # --------------------在类中封装属性名-------------------------
"""
Python 程序员不去依赖语言特性去封装数据,而是通过遵循一定的属性和方法命
名规约来达到这个效果。
第一个约定是任何以单下划线开头的名字都应该是内部实现。
使用下划线开头的约定同样适用于模块名和模块级别函数。
使用双下划线开始会导致访问名称变成其他形式,这种属性通过继承是无法被覆盖的。
大多数而言,你应该让你的非公共名称以单下划线开头。
但是,如果你清楚你的代码会涉及到子类,
并且有些内部属性应该在子类中隐藏起来,
那么才考虑使用双下划线方案。 有时候你定义的一个变量和某个保留关键字冲突,这时候可以使用单下划线作为后缀 """ # ---------------------创建一个可管理的属性------------------------------
# 给某个实例attribute 增加除访问与修改之外的其他处理逻辑,比如类型检查或合法性验证
# 自定义某个属性的一种简单方法是将它定义为一个property
class Person:
def __init__(self, name, password):
self.name = name
self.password = password @property
def name(self):
return self._name # @property
# def password(self):
# return self._password @name.setter
def name(self, value):
if not isinstance(value, str):
raise TypeError('Excepted a string')
self._name = value @name.deleter
def name(self):
raise AttributeError("Can't delete sttribute") p = Person('qf','pass')
print(p.name)
# p.name = 16
# 还能在已存在的get 和set 方法基础上定义property
# class Person:
# def __init__(self, name):
# self.set_name(name)
#
# def get_name(self):
# return self._name
#
# def set_name(self, value):
# if not isinstance(value, str):
# raise TypeError('Excepted a string')
# self._name = value
#
# name = property(get_name, set_name)
#
# p = Person('qf')
# p.name = 13 """
上述代码中有三个相关联的方法,这三个方法的名字都必须一样。第一个方法是一
个getter 函数,它使得first name 成为一个属性。其他两个方法给first name 属
性添加了setter 和deleter 函数。需要强调的是只有在first name 属性被创建后,
后面的两个装饰器@first name.setter 和@first name.deleter 才能被定义。 property 的一个关键特征是它看上去跟普通的attribute 没什么两样,但是访问它
的时候会自动触发getter 、setter 和deleter 方法。 一个property 属性其实就是一系列相关绑定方法的集合 """ # --------------------调用父类方法---------------------------
# 在子类中调用父类的某个已经被覆盖的方法
# 为了调用父类(超类) 的一个方法,可以使用super() 函数
class A:
def __init__(self):
self.x = 0 class B(A):
def __init__(self):
super.__init__()
self.y = 1
"""
对于你定义的每一个类,Python 会计算出一个所谓的方法解析顺序(MRO) 列表。
这个MRO列表就是一个简单的所有基类的线性顺序表
为了实现继承,Python 会在MRO 列表上从左到右开始查找基类,
直到找到第一个匹配这个属性的类为止。 MRO 列表的构造是通过一个C3 线性化算法来实现的:合并所有父类的MRO列表并遵循如下三条准则:
• 子类会先于父类被检查
• 多个父类会根据它们在列表中的顺序被检查
• 如果对下一个类存在两个合法的选择,选择第一个父类 只是想简单的自定义某个类的单个属性访问的话就不用去写描述器了。
这种情况下使用property 技术会更加容易。
当程序中有很多重复代码的时候描述器就很有用了(比如你想在你代码的很多地方使用描述器
提供的功能或者将它作为一个函数库特性)。 """ # -----------------------创建新的类或实例属性---------------------------------
# 创建一个全新的实例属性,可以通过一个描述器类的形式来定义它的功能
class IntegerU:
def __init__(self, name):
self.name = name def __get__(self, instance, cls):
if instance is None:
return self
else:
return instance.__dict__[self.name] def __set__(self, instance, value):
if not isinstance(value, int):
raise TypeError('Excepted an int')
instance.__dict__[self.name] = value def __delete__(self, instance):
del instance.__dict__[self.name]
"""
一个描述器就是一个实现了三个核心的属性访问操作(get, set, delete) 的类,
分别为get () 、set () 和delete () 这三个特殊的方法。
这些方法接受一个实例作为输入,之后相应的操作实例底层的字典。 """
# 为了使用一个描述器,需将这个描述器的实例作为类属性放到一个类的定义中
# 描述器的一个比较困惑的地方是它只能在类级别被定义,而不能为每个实例单独定义
# Example
class Point:
x = IntegerU('x')
y = IntegerU('y') def __init__(self, x, y):
self.x = x
self.y = y point = Point(2, 3)
print(point.x)
# point.x = 2.33 # ---------------------简化数据结构的初始化--------------------------
# 在一个基类中写一个公用的init () 函数
class Structure:
_fields = [] def __init__(self, *args, **kwargs):
if len(args) != len(self._fields):
raise TypeError('Excepted {} arguments'.format(len(self._fields))) for name, value in zip(self._fields, args):
setattr(self, name, value) extra_args = kwargs.keys() - self._fields
for name in extra_args:
setattr(self, name, kwargs.pop(name)) if kwargs:
raise TypeError('Duplicate values for {}'.format(','.join(kwargs))) # ----------------------定义接口或者抽象基类---------------------------------
# 定义一个接口或抽象类,并且通过执行类型检查来确保子类实现了某些特定的方法
# 使用abc 模块可以很轻松的定义抽象基类
from abc import ABCMeta, abstractclassmethod class IStream(metaclass=ABCMeta):
@abstractclassmethod
def read(self, maxbytes=-1):
pass @abstractclassmethod
def write(self, data):
pass
"""
抽象类的一个特点是它不能直接被实例化
抽象类的目的就是让别的类继承它并实现特定的抽象方法 """
class SocketStream(IStream):
def read(self, maxbytes=-1):
pass def write(self, data):
pass # -------------------在类中定义多个构造器-------------------------
# 为了实现多个构造器,需要使用到类方法
# 类方法的一个主要用途就是定义多个构造器。它接受一个class 作为第一个参数(cls)
import time class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day @classmethod
def today(cls):
t = time.localtime()
return cls(t.tm_year, t.tm_mon, t.tm_mday) a = Date(2018, 8, 8)
b = Date.today()
print(b.year) # 可以通过new() 方法创建一个未初始化的实例

Python--进阶处理8的更多相关文章

  1. Python进阶:函数式编程实例(附代码)

    Python进阶:函数式编程实例(附代码) 上篇文章"几个小例子告诉你, 一行Python代码能干哪些事 -- 知乎专栏"中用到了一些列表解析.生成器.map.filter.lam ...

  2. Python进阶 - 对象,名字以及绑定

    Python进阶 - 对象,名字以及绑定 1.一切皆对象 Python哲学: Python中一切皆对象 1.1 数据模型-对象,值以及类型 对象是Python对数据的抽象.Python程序中所有的数据 ...

  3. Python进阶-继承中的MRO与super

    Python进阶-继承中的MRO与super 写在前面 如非特别说明,下文均基于Python3 摘要 本文讲述Python继承关系中如何通过super()调用"父类"方法,supe ...

  4. Python进阶 - 命名空间与作用域

    Python进阶 - 命名空间与作用域 写在前面 如非特别说明,下文均基于Python3 命名空间与作用于跟名字的绑定相关性很大,可以结合另一篇介绍Python名字.对象及其绑定的文章. 1. 命名空 ...

  5. python进阶学习笔记(一)

    python进阶部分要学习的内容: 学习目标: 1.函数式编程 1.1,什么是函数式编程 函数式编程是一种抽象计算的编程模式 不同语言的抽象层次不同: 函数式编程的特点: python支持的函数式编程 ...

  6. 【python进阶】详解元类及其应用2

    前言 在上一篇文章[python进阶]详解元类及其应用1中,我们提到了关于元类的一些前置知识,介绍了类对象,动态创建类,使用type创建类,这一节我们将继续接着上文来讲~~~ 5.使⽤type创建带有 ...

  7. 【python进阶】Garbage collection垃圾回收2

    前言 在上一篇文章[python进阶]Garbage collection垃圾回收1,我们讲述了Garbage collection(GC垃圾回收),画说Ruby与Python垃圾回收,Python中 ...

  8. Python进阶 函数式编程和面向对象编程等

    函数式编程 函数:function 函数式:functional,一种编程范式.函数式编程是一种抽象计算机的编程模式. 函数!= 函数式(如计算!=计算机) 如下是不同语言的抽象 层次不同 高阶函数: ...

  9. 【python进阶】深入理解系统进程2

    前言 在上一篇[python进阶]深入理解系统进程1中,我们讲述了多任务的一些概念,多进程的创建,fork等一些问题,这一节我们继续接着讲述系统进程的一些方法及注意点 multiprocessing ...

  10. Python进阶:如何将字符串常量转化为变量?

    前几天,我们Python猫交流学习群 里的 M 同学提了个问题.这个问题挺有意思,经初次讨论,我们认为它无解. 然而,我认为它很有价值,应该继续思考怎么解决,所以就在私密的知识星球上记录了下来. 万万 ...

随机推荐

  1. Memcached真的过时了吗?

    Memcached真的过时了吗? 这两年Redis火得可以,Redis也常常被当作Memcached的挑战者被提到桌面上来.关于Redis与Memcached的比较更是比比皆是.然而,Redis真的在 ...

  2. AngularJS中的$apply

    $apply()方法可以在angular框架之外执行angular JS的表达式,例如:DOM事件.setTimeout.XHR或其他第三方的库. 当仅仅使用Angular所提供的对象时,你不该过多的 ...

  3. 彻底清除Linux centos minerd木马 实战  跟redis的设置有关

    top -c把cpu占用最多的进程找出来: Tasks: total, running, sleeping, stopped, zombie Cpu(s): 72.2%us, 5.9%sy, 0.0% ...

  4. CentOS 6.2下log4cplus的使用

    一.简介 log4cplus是一款优秀的基于C/C++的开源日志库.log4cplus具有线程安全,不用但心在多线程状态下写日志问题:使用灵活,可通过配置文件设置日志级别下输出位置,还可以在程序运行时 ...

  5. spring boot文件上传、下载

    主题:Spring boot 文件上传(多文件上传)[从零开始学Spring Boot]http://www.iteye.com/topic/1143595 Spring MVC实现文件下载http: ...

  6. Hive使用过程中的坑

    在Hive脚本中如果有 use db; #即使用数据库 最后一定要有一个exit;脚本,退出hive窗口 否则运行到最后,hive无法启动MR任务,只是卡在打印完成hive脚本处. 例子如下: $Hi ...

  7. rpc 理解

    RPC=Remote Produce Call 是一种技术的概念名词. HTTP是一种协议,RPC可以通过HTTP来实现,也可以通过Socket自己实现一套协议来实现. rpc是一种概念,http也是 ...

  8. Spring整合redis,通过sentinel进行主从切换

    实现功能描述: redis服务器进行Master-slaver-slaver-....主从配置,通过2台sentinel进行failOver故障转移,自动切换,采用该代码完全可以直接用于实际生产环境. ...

  9. poj3067 Japan(树状数组)

    转载请注明出处:http://blog.csdn.net/u012860063 题目链接:id=3067">http://poj.org/problem? id=3067 Descri ...

  10. C语言 · 排列数

    算法提高 排列数   时间限制:1.0s   内存限制:256.0MB      问题描述 0.1.2三个数字的全排列有六种,按照字母序排列如下: 012.021.102.120.201.210 输入 ...