python语言特性
python
装饰器
def log(func):
    @functools.wraps			# 实现 wrapper.__name__ = func.__name__
    def wrapper(*args, **kw):
    	print("befor")
        ret = func()
        print("after")
        return ret
    return wrapper
@log		# 相当于执行了 fun=log(fun),函数名也会变为 wrapper
def fun():
    pass
def log(text):
    def decorator(func):
        @functools.wraps
        def wrapper(*args, **kw):
            ret = func(*args, **kw)
            return ret
        return wrapper
    return decorator
@log("string")	# 先执行log(),再执行 fun=decorator(fun),函数名变为 wrapper
def fun():
    pass
类
type 与类
Hello = type('Hello', (object,), dict(hello=fn))  # class 名称,要继承的类,要绑定的方法
# 等于 
class Hello(object):
    def hello():
        pass
_new_
__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass。
- __new__是一个静态方法,而__init__是一个实例方法
- __new__方法会返回一个创建的实例,而__init__什么都不返回
- 只有在__new__返回一个cls的实例时,后面的__init__才能被调用
- 当创建一个新实例时调用_new_,初始化一个实例时用_init_
私有变量__var可通过obj._Obj__var
from enum import Enum, unique
@unique
class Weekday(Enum):
    Sun = 0 # Sun的value被设定为0
    Mon = 1
    Tue = 2
    Wed = 3
    Thu = 4
    Fri = 5
    Sat = 6
_slots_
在动态运行期间给类绑定一个方法,所有实例都能使用。
class Obj(Object):
    __slots__ = ('name', 'age')	# 限制类只能绑定一定的属性,对子类无用
#  若子类有__slots__,则子类允许定义的属性为自身__slots__与父类__slots__
property
setter getter
class Student(object):
    @property
    def score(self):
        return self._score
    @score.setter			# 不设置 score.setter 即为只读属性
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value
metaclass 元类
先定义metaclass,就可以创建类,最后创建实例
# metaclass是类的模板,所以必须从`type`类型派生:
class ListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)
        return type.__new__(cls, name, bases, attrs)
    
    
class MyList(list, metaclass=ListMetaclass):
    pass
当我们传入关键字参数metaclass时,魔术就生效了,它指示Python解释器在创建MyList时,要通过ListMetaclass.__new__()来创建,在此,我们可以修改类的定义
__new__()方法接收到的参数依次是:
- 当前准备创建的类的对象;
- 类的名字;
- 类继承的父类集合;
- 类的方法集合。
例子: ORM 框架
单元测试
import unittest
from mydict import Dict
class TestDict(unittest.TestCase):
    def test_init(self):
        d = Dict(a=1, b='test')
        self.assertEqual(d.a, 1)
        self.assertEqual(d.b, 'test')
        self.assertTrue(isinstance(d, dict))
    def test_attr(self):
        d = Dict()
        d.key = 'value'
        self.assertTrue('key' in d)
        self.assertEqual(d['key'], 'value')
    def test_keyerror(self):
        d = Dict()
        with self.assertRaises(KeyError):
            value = d['empty']
            
    def setUp(self):
        """每个测试方法前执行"""
        print('setUp...')
            
    def tearDown(self):
        """每个测试方法执行后执行"""
        print('tearDown...')
多进程
from multiprocessing import Process
import os
# 子进程要执行的代码
def run_proc(name):
    print('Run child process %s (%s)...' % (name, os.getpid()))
if __name__=='__main__':
    print('Parent process %s.' % os.getpid())
    p = Process(target=run_proc, args=('test',))
    print('Child process will start.')
    p.start()
    p.join()
    print('Child process end.')
from multiprocessing import Pool
import os, time, random
def long_time_task(name):
    print('Run task %s (%s)...' % (name, os.getpid()))
    start = time.time()
    time.sleep(random.random() * 3)
    end = time.time()
    print('Task %s runs %0.2f seconds.' % (name, (end - start)))
if __name__=='__main__':
    print('Parent process %s.' % os.getpid())
    p = Pool(4)
    for i in range(5):
        p.apply_async(long_time_task, args=(i,))
    print('Waiting for all subprocesses done...')
    p.close()
    p.join()
    print('All subprocesses done.')
子进程:
r = subprocess.call(['nslookup', 'www.python.org'])
子进程接收输入:
import subprocess
p = subprocess.Popen(['nslookup'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, err = p.communicate(b'set q=mx\npython.org\nexit\n')
print(output.decode('utf-8'))
print('Exit code:', p.returncode)
Threadlocal
import threading
    
# 创建全局ThreadLocal对象:
local_school = threading.local()
def process_student():
    # 获取当前线程关联的student:
    std = local_school.student
    print('Hello, %s (in %s)' % (std, threading.current_thread().name))
TCP
客户端:
# 导入socket库:
import socket
# 创建一个socket:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接:
s.connect(('www.sina.com.cn', 80))
# 发送数据:
s.send(b'GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n')
# 接收数据:
buffer = []
while True:
    # 每次最多接收1k字节:
    d = s.recv(1024)
    if d:
        buffer.append(d)
    else:
        break
data = b''.join(buffer)
# 关闭连接:
s.close()
服务端:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 监听端口:
s.bind(('127.0.0.1', 9999))
s.listen(5)
while True:
    # 接受一个新连接:
    sock, addr = s.accept()
    # 创建新线程来处理TCP连接:
    t = threading.Thread(target=tcplink, args=(sock, addr))
    t.start()
    
def tcplink(sock, addr):
    print('Accept new connection from %s:%s...' % addr)
    sock.send(b'Welcome!')
    while True:
        data = sock.recv(1024)
        time.sleep(1)
        if not data or data.decode('utf-8') == 'exit':
            break
        sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))
    sock.close()
    print('Connection from %s:%s closed.' % addr)
UDP
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定端口:
s.bind(('127.0.0.1', 9999))
while True:
    # 接收数据:
    data, addr = s.recvfrom(1024)
    print('Received from %s:%s.' % addr)
    s.sendto(b'Hello, %s!' % data, addr)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for data in [b'Michael', b'Tracy', b'Sarah']:
    # 发送数据:
    s.sendto(data, ('127.0.0.1', 9999))
    # 接收数据:
    print(s.recv(1024).decode('utf-8'))
s.close()
协程 异步
async def hello():
    print("Hello world!")
    r = await asyncio.sleep(1)	# 此处为异步非阻塞IO,cpu不再等待,而是执行其他。当iO结束后再转来执行
    print("Hello again!")
type object class
一切类都继承自object,一切类都是type的实例(type也是其自身的实例)

变量类型
- None(全局只有一个)
- 数值
- 迭代类型
- 序列类型
- 映射
- 集合
- 上下文管理类型(with语句)
- 其他(模块、函数、代码、方法等)
len方法
一般为调用 len,当参数为list、dict、set等时直接调用对象内部保存的长度,此处为解释器优化
抽象基类
# 可以实现,但是只有在调用方法时才报错
class Base(Object):
      raise NotImplementedError
import abc
class Base(metaclass=abc.ABCMeta):
      @abc.abstractmethos            # 加上后就无需抛出异常了
      def fun(self):
            pass
# 在对其或其子类初始化时就会抛出异常,不常使用,更推荐用鸭子类型、多继承
常用基类在collections.abc下
类属性与实例属性
class A(object):
    aa = 1
a = A()
print(A.aa) # 1
print(a.aa) # 1  在实例中没查找到aa属性,向上到类中查找
a.aa = 100  # 此时给实例也添加了一个 aa 属性
print(A.aa) # 1
print(a.aa) # 100
查找顺序
由下向上
c3算法,MRO序列:
https://blog.csdn.net/u011467553/article/details/81437780
https://lotabout.me/2020/C3-Algorithm/
一般多继承使用深度遍历,菱形继承使用广度遍历
当调用super().__init__()时,调用的的是MRO序列中的下一个类。
可用obj.__mro__查看
静态方法、类方法、对象方法以及参数
普通方法与实例绑定,静态方法与类绑定
class Obj(object):
    def fun(self, *arg):
        pass
    # 普通实例方法,运行时是 fun(实例, *arg)
    @staticmethod
    def static_fun():
        return Obj()
    # 静态方法,运行时与普通函数无异。但调用方法为 Obj.static_fun()
    # 但返回的对象为硬编码进去的,当方法与这个类无关时使用它
    @classmethod
    def class_fun(cls, *arg):
        return cls(*arg)
    # 类方法,将类这个对象作为第一个参数传入
    # 在类改名后依然可以正常使用
自省
obj.__dir__对应的是属性字典。对其操作相当于操作对象的属性。但其中不包含继承的属性。
dir(obj)得到的包括自己的与继承的属性与方法。
mixin 模式
类似java中接口。这是一种编码方法,类以XXXMixin命名
特点:
- 功能单一
- 不和基类关联,可以和任意基类组合
- 不再mixin中使用super()
上下文管理器协议
实现__enter__ __exit__后即可使用with语句
进入with语句后最先调用__enter__
退出with语句时最后调用__exit__
利用contextlib库可以更快的实现
@contextlib.contextmanager
def file_open(file_name):
	print("befor open file")
	yield {}
	print("after open file")
with file_open("file.txt") as f:
      print("file processing")
# befor open file
# file processing
# after open file
python 变量
python的变量都是指针,指向赋值的目标。
class Com(object):
    def __init__(self, staffs=[]):
        self.staffs = staffs
    def add(self, user):
        self.staffs.append(user)
    def remove(self, user):
        self.staffs.remove(user)
com1 = Com([1,2,3])
print(com1.staffs)          # [1, 2, 3]
com2 = Com()
com2.add("person1")
print(com2.staffs)          # ['person1']
com3 = Com()
com2.add("person2")
print(com1.staffs)          # [1, 2, 3]
print(com3.staffs)          # ['person1', 'person2']
print(com3.staffs)          # ['person1', 'person2']
print(com2.staffs is com3.staffs)       # True
print(Com.__init__.__defaults__)        # (['person1', 'person2'],)
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号