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

# --------------改变对象的字符串显示----------------------
# 要改变一个实例的字符串表示,可重新定义它的__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. 随机用户id号,随机密码用户名

    类似新浪微博的用户Id怎么生成呢? 特点:10位随机数,而且是以1开头的 好处:不容易猜出有多少用户 方法一: 目的是生成唯一id.可以用uniqid.uniqid获取一个字符串,循环这个字符串,把每 ...

  2. Angularjs $http.post

    $http.post 采用postJSON方式发送数据到后台. 如果不需要发送json格式数据,序列化成&连接的字符串,形如:"a=1&b=2",最终完整的前端解决 ...

  3. HBase源代码分析之HRegionServer上MemStore的flush处理流程(二)

    继上篇文章<HBase源代码分析之HRegionServer上MemStore的flush处理流程(一)>遗留的问题之后,本文我们接着研究HRegionServer上MemStore的fl ...

  4. UISCREEN 和支持高分辨率的显示屏

    UIScreen对象包含了整个屏幕的边界矩形.当构造应用的用户界面接口时,你应该使用该对象的属性来获得推荐的矩形大小,用以构造你的程序窗口. CGRect bound = [[UIScreen mai ...

  5. git 的一些笔记

    git config git config存在三个地方 :1./.git/config 项目级别2.~/.gitconfig 用户级别3./etc/gitconfig 系统级别 git config ...

  6. 关于HashMap初始化容量问题

    使用阿里云代码规范插件扫描后出现以下提示: hashmap should set a size when initalizing,即hashmap应该在初始化时设置一个大小 在网上搜到一篇讲解(htt ...

  7. 基于jQuery页面窗口拖动预览效果

    今天给大家分享一款基于Query页面窗口拖动预览效果.这是一款基于jQuery+HTML5实现的模拟页面窗口显示拖动窗口预览特效.这款实例适用浏览器:IE8.360.FireFox.Chrome.Sa ...

  8. 卖座网一处SQL注射(Http Referer sqlinjection)

    漏洞作者: 猪猪侠 漏洞详情 披露状态: 2015-01-13: 细节已通知厂商并且等待厂商处理中2015-01-14: 厂商已经确认,细节仅向厂商公开2015-01-24: 细节向核心白帽子及相关领 ...

  9. C# 注册表修改 立即生效 [转]

    修改注册表后不重启计算机边生效. const int WM_SETTINGCHANGE = 0x001A; const int HWND_BROADCAST = 0xffff; IntPtr resu ...

  10. HttpURLConnection的使用

    import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; ...