前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python指南:高级程序设计之面向对象程序设计进阶

Python指南:高级程序设计之面向对象程序设计进阶

作者头像
王强
发布2018-08-09 18:09:37
8580
发布2018-08-09 18:09:37
举报
文章被收录于专栏:Python爬虫实战Python爬虫实战

本节中,我们将更深入地学习 Python 对面向对象的支持,学习很多可以减少必须编写的代码的总量、拓展程序的威力与功能的技术。下面以一个简单的类开始:

代码语言:javascript
复制
# 简单类定义
class Point:
    __slots__ = ("x", "y")
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

__slots__ 限制了 Point 能添加的属性只有 xy 。下面测试一下:

代码语言:javascript
复制
pt = Point()
pt.x = 1
pt.y = 2
pt.z = 3

[out]
Traceback (most recent call last):

  File "<ipython-input-1-88952c59b8ad>", line 11, in <module>
    pt.z = 3

AttributeError: 'Point' object has no attribute 'z'

可以看出不能给 pt 中没有定义的属性赋值,下面去掉 __slots__ 所在行:

代码语言:javascript
复制
class Point2:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

pt = Point2()
pt.x = 1
pt.y = 2
pt.z = 3

上面这段程序可以正常运行。

01.控制属性存取

控制属性存取

Python中定义了一些用于属性存取的特殊方法:

方法名称

使用

描述

__delattr__(self, name)

del x.n

删除对象x的属性

__dir__(self)

dir(x)

返回x的属性名列表

__getattr__(self, name)

v = x.n

返回对象x的n属性值

__getattribute__(self, name)

v = x.n

返回对象x的n属性值

__setattr__(self, name)

x.n = v

将对象x的n属性名值设为v

__getattr____getattribute__ 的主要区别:

  1. __getattrobute__() 只要涉及到实例属性的访问就会调用该方法,如果属性不存在会抛出AttributeError 异常。
  2. __getattr__() 在以下情况下调用:
  • 属性不在实例的dict中;
  • 属性不在其基类以及祖先类的dict 中;
  • 触发AttributeError 异常时(不仅仅是get_attribute() 引发的异常,property中定义的get() 方法抛出的异常也会调用该方法。

3.当__getattr____getattribute__ 同时被定义时,要么显示在__getattribute__ 中调用,要么抛出AttributeError异常,否则__getattr__ 永远不会被调用。

下面定义了一个简单的 “常数” 类,可以正常的设置任意属性,但如果想要去改变或者删除该属性,则会产生异常。

代码语言:javascript
复制
class Const:
    def __setattr__(self, name, value):
        if name in self.__dict__:
            raise ValueError("cannot change a const attribute")
        self.__dict__[name] = value

    def __delattr__(self, name):
        if name in self.__dict__:
            raise ValueError("cannot delete a const attribute")
        raise AttributeError("'{0}' object has no attribute '{1}'"
                             .format(self.__class__.__name__, name))

测试1:

代码语言:javascript
复制
# 尝试改变属性      
const = Const()
const.limit = 51
const.limit = 20

[out]
Traceback (most recent call last):

  File "<ipython-input-6-16721df7d195>", line 3, in <module>
    const.limit = 20

  File "<ipython-input-4-92afbeaa4fd4>", line 4, in __setattr__
    raise ValueError("cannot change a const attribute")

ValueError: cannot change a const attribute

测试2:

代码语言:javascript
复制
# 尝试删除属性
del const.limit

[out]
Traceback (most recent call last):

  File "<ipython-input-7-c88698f71e6c>", line 1, in <module>
    del const.limit

  File "<ipython-input-4-92afbeaa4fd4>", line 9, in __delattr__
    raise ValueError("cannot delete a const attribute")

ValueError: cannot delete a const attribute

02.函子

在计算机科学中,函子是指一个对象,该对象可以向函数一样进行调用,在 Python 中,函子就是另一种类型的函数对象。任何包含了特殊方法 __call__() 的类都是一个函子。函子可以提供的关键好处是可以维护一些状态信息

下面定义一个去除字符串末尾符号的函子:

代码语言:javascript
复制
# 函子
class Strip:
    def __init__(self, characters):
        self.characters = characters

    def __call__(self, string):
        return string.strip(self.characters)

使用示例:

代码语言:javascript
复制
st = Strip(',;:.!?')
result = st('Hello Python!')
print(result)

[out]
Hello Python

03.上下文管理器

前面的文件操作部分,已经见过 with open() 了,with 就是上下文管理器的标志。使用上下文管理器可以简化代码,这是通过确保某些操作在特定代码块执行前与执行后再进行来实现的。之所以可以做到这样,是因为上下文管理器提供了两个特殊方法 :__enter__()__exit__()。在 with 语句内创建上下文管理器时,其 __enter__()方法会自动被调用,在 with 语句后、上下文管理器作用范围之外时,其__exit__() 方法会自动被调用。使用上下文管理器的语法如下:

代码语言:javascript
复制
with expression as variable:
    suite

expression 部分必须是或者必须可以生成一个上下文管理器。

下面两个代码片段实现的功能一致,来体验一些上下文管理器的魅力吧:

代码语言:javascript
复制
filename = 'd:/open.txt'

# open 正常使用
content = ''
fh = None
try:
    fh = open(filename)
    for line in fh:
        content += line
except EnvironmentError as err:
    print(err)
finally:
    if fh is not None:
        fh.close()

# open 上下文管理器用法
content = ''
try:
    with open(filename) as fh:
        for line in fh:
            content += line
except EnvironmentError as err:
    print(err)          

系列文章推荐

┣ Python指南:Python的8个关键要素

┣ Python指南:数据类型

┣ Python指南:组合数据类型

┣ Python指南:控制结构与函数

┣ Python指南:面向对象程序设计

┣ Python指南:文件处理

┣ Python指南:高级程序设计之过程型程序设计进阶

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-07-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 C与Python实战 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档