python特性语言_python语言特性

本文深入探讨了Python编程中的装饰器、元类、多进程、多线程和协程等高级特性。通过实例展示了如何使用装饰器实现日志功能,元类自定义类的行为,以及如何进行并发和异步编程以提升程序效率。同时,还涵盖了子进程的管理、上下文管理器协议和线程局部存储等概念。
摘要由CSDN通过智能技术生成

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__()方法接收到的参数依次是:

当前准备创建的类的对象;

类的名字;

类继承的父类集合;

类的方法集合。

单元测试

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也是其自身的实例)

847afbe01134af54520eaad7438ea630.png

变量类型

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

查找顺序

当调用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'],)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值