类与对象 (01)

周六又进了趟城, 跟刚从北京过来的小陆学姐, 山大硕士毕业, 然后在四大干了几年, 现在腾讯一部门做战略顾问, 就是很优秀哇. 回顾了一些校园生活, 职场经历, 职场江湖, 还有一些逸闻趣事, 就聊得很嗨. 得出的几个关键结论如下:

  • 企业的文化, 价值观, 战略, 受领导人影响很大

  • 从适普和概率观点来看, 一个人竞争力是, 高学历 + 行业经验, 学历尤为重要

  • 选择领导很重要, 就一个原则: 头脑在线, 人靠谱, 头脑(智商 + 情商) 尤为重要

  • 物以类聚, 人以群分, 不得不承认, 在职场上也是这个自然法则

  • 跳槽其实涨薪水最快的方式, 但前提是, 你在岗期给东家做出了成绩, 同时自己能力不断增强, 且岗位不换

  • 要有职业素养, 最为重要的是, 专业性 + 责任感. 二者同等重要, 这也是凸显了教育培养的重要性

  • 要有底线. 法律和道德的底线, 难免是会涉及到这些敏感区, 需要去挑战试探, 同时也要能搂住底线

感觉我还是见识不够哇, 我其实很害怕改变, 所有就基本不做商业这块, 只是做些数据, IT 这块, 比较客观, 纯粹, 可以保持住初心的一些事情, 一直在坚持着.

不扯了...继续温习下类和对象的一些旧知识, 和新的补充.

围绕 类定义相关的编程模型, 如 Python 特性, 特殊方法使用, 类封装技术, 继承, 内存管理, 设计模式这些

改变对象的字符串显示

需求

改变对象实例的打印或显示输出, 让她们更具有可读性

方案

通过重写 _ _ str _ _() 和 _ _ repr _ _ () 方法实现

class Pair:
    def __init__(self, x, y):
        self.x = x
        self.y = y 
    
    def __repr__(self):
        return f'Pair({self.x}, {self.y})'
    
    def __str__(self):
        return f'{self.x}, {self.y}'
    
# test 
p = Pair(1, 2)

print(p)
p
1, 2
Pair(1, 2)

__ str __ () 在 print( 实例对象 obj) 时会自动调用. 即将一个对象转为一个字符串, 通常是将对象的一些属性信息给打印出来呀.

__ repr __ () 方法返回一个实例的代码表示形式, 常用用来重新构造该实例, 内置的 repr() 返回一个字符串, 通常是 repr() 和 eval () 是一个互逆的过程.

# veal: 字符串转为对象 
my_str = '{"name": "youge", "age":18}'

str_to_obj = eval(my_str)

print(type(str_to_obj), str_to_obj)

# repr: 对象转字符串 
obj_to_str = str_to_obj.__repr__()

print(type(obj_to_str), obj_to_str)
<class 'dict'> {'name': 'youge', 'age': 18}

<class 'str'> {'name': 'youge', 'age': 18}

让对象支持上下文管理

需求

让对象能使用上下文管理, 即用 with 语句

方案

通过实现 __ enter __ () 和 __ exit __ () 方案, 即能用 with 语句.

跟 for 迭代一样的, for 实现的是 __ iter __ 和 __ next __ 方法

from socket import socket, AF_INET, SOCK_STREAM 
from functools import partial 

class LasyConnection: 
    def __init__(self, address, family=AF_INET, type=SOCK_STREAM):
        self.address = address
        self.family = family
        self.type = type 
        self.sock = None 
        
    def __enter__(self):
        if self.sock is not None:
            raise RuntimeError('Already connected')
        # 创建套接字并连接
        self.sock = socket(self.family, self.type)
        self.sock.connect(self.address)
        return self.sock 
        
    def __exit__(self, exc_ty, exc_val, error):
        self.sock.close()
        self.sock = None 
        
# test 
con = LasyConnection(('www.baidu.com', 80))

with con as s:
    s.send(b'xxxxxxxx')
    s.send(b'aaaaa')
    resp = b''.join(iter(partial(s.recv, 8888), b''))

编写上下文管理器的主要原理是, 编写的代码会放到 with 语句块中执行.

  • 首先, 当遇到 with 语句时, __ enter __ () 方法会被自动触发. 它的返回值 (如果有) 会被赋值 as 声明的变量. 如 'with open(xxx) as f ' 这个 f 的值即为 __ enter __ () 方法的返回值.
  • 然后, with 语句块中的代码继续开始运行 ... (业务逻辑)
  • 最后, __ exit __ () 方法会被触发, 并进行清理工作.
# 不需要 调用 close() 的原因, 因为 with 执行结束后会自动清理

with open('xxxx', 'r') as f:
    pass 

不论 with 代码块中发生什么, 上面的控制流都会执行完, 即便发生异常. 事实上, __ exit __ () 方法的第三个参数包含了异常类型, 异常值和追溯信息(如果有). 同时 __ exit __ () 方法能自己决定如何利用这个异常信息, 或者忽略并发返回一个 None. 如果 __ exit __ () 返回 True, 则异常会被清空, with 语句后面的话继续执行.

上面的这个版本呢, 只能允许一个 with 语句来连接, 一个 socket 显然不行, 于是来改成这样的.

from socket import socket, AF_INET, SOCK_STREAM 

class LasyConnection: 
    def __init__(self, address, family=AF_INET, type=SOCK_STREAM):
        self.address = address
        self.family = family
        self.type = type 
        self.connections = []
        
    def __enter__(self):
        # 创建套接字并连接
        sock = socket(self.family, self.type)
        sock.connect(self.address)
        # 将每个 socket 都存起来
        self.connections.append(sock)
        return self.sock 
        
    def __exit__(self, exc_ty, exc_val, error):
        self.connections.pop().close()
        
# test 
con = LasyConnection(('www.baidu.com', 80))

with con as s1:
    pass 
    with con as s2:
        pass
    # s1 and s2 are independent sockets 

LasyConnection 类就可以看做是一个连接工厂. 在内部, 构造了一个栈 (列表) . 每次 __ enter __ 方法被调用, 就会复制一个新的连接并加入到栈中. 同时 __ exit __ 方法会从栈中 pop 出最后一个 sockets 兄弟给给关闭掉. 它可以允嵌套多个 with 语句创建多连接.

在管理一些资源文件, 网络连接, 和锁的场景中, 用上下文管理器是非常普遍的. 它们的共同特点是, 必须被手动的关闭或释放来确保程序的正确运行. 如果请求了一个锁, 则必须用后要手动释放, 不然就死锁了. 而通过 实现 __ enter __ 和 __ exit __ 方法 并用 with 语句则可很容易避免这些问题, 因为有 __ exit __ 方法安排上了.

posted @ 2020-07-19 22:17  致于数据科学家的小陈  阅读(133)  评论(0编辑  收藏  举报