Antkillerfarm Hacking V8.5

language » Python(三)

2018-12-10 :: 6660 Words

Python

@的用法

@在python中是装饰器的意思,它的用法比较复杂。假设我们要增强函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。

def timer(func):
  def f(x, y=10):
    before = time()
    rv = func(x, y)
    after = time()
    print('time taken: ', after - before)
    return rv
  return f

@timer
def add(x, y=10):
  return x + y

装饰器接受func作为参数,并返回装饰好之后的func。上例等价于:

f = timer(add)
f(x,y)

此外还有类装饰器,其一般签名如下:

def cls_decorator(cls: type[T]) -> type[T]:

在python 3.5以后,@是一个操作符,表示矩阵-向量乘法。

A@x就是矩阵-向量乘法np.dot(A, x)

参见:

https://www.zhihu.com/question/26930016

如何理解Python装饰器?

https://mp.weixin.qq.com/s/1QjJqFfJNNych9b6ae5VUg

深入理解Python装饰器

https://www.liaoxuefeng.com/wiki/1016959663602400/1017502538658208

使用@property

https://www.liaoxuefeng.com/wiki/1016959663602400/1017451662295584

装饰器

https://mp.weixin.qq.com/s/qMT46hjOQeXsjVpZPqLRVA

一文读懂Python装饰器

https://mp.weixin.qq.com/s/_ZvF6jK5Jo4rFGwHvEoAig

一文读懂Python装饰器由来

https://mp.weixin.qq.com/s/Wsk6H3Z6HwGPKTRNYc2cLw

一个已经存在10年,却被严重低估的库(decorator)

importlib

使用importlib动态导入库和类的示例:

m = importlib.import_module(library_name)
model_cls = getattr(m, class_name)

闭包

在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。闭包可以用来在一个函数与一组“私有”变量之间创建关联关系。在给定函数被多次调用的过程中,这些私有变量能够保持其持久性。

用比较容易懂的人话说,就是当某个函数被当成对象返回时,夹带了外部变量,就形成了一个闭包。

https://mp.weixin.qq.com/s/qYKNGqItnSXq0-Zq2kMCKA

聊一聊Python中的闭包

@classmethod和@staticmethod

class A(object):
    def foo(self, x):
        print("executing foo(%s,%s)" % (self, x))
        print('self:', self)
    @classmethod
    def class_foo(cls, x):
        print("executing class_foo(%s,%s)" % (cls, x))
        print('cls:', cls)
    @staticmethod
    def static_foo(x):
        print("executing static_foo(%s)" % x)

@classmethod类似于C++中的static,无须实例化就可以调用。@staticmethod则是普通成员函数的简写。python一般用cls表示类,而用self表示类的实例。当然,这只是编程规范的约束,而非编译器约束,使用其他名字也是可以的。

参考:

https://www.cnblogs.com/elie/p/5876210.html

python中@classmethod @staticmethod区别

class的另类用法

由于python是动态脚本语言,它的class的用法也非常灵活。你甚至无须事先定义类的成员变量,而只需要运行时添加即可。

示例:

class A():
    pass

a=A()
a.name = "Job"
a.age = 10

多继承 & 多重继承

class Displayer():
    def display(self, message):
        print(message)


class LoggerMixin():
    def log(self, message, filename='logfile.txt'):
        with open(filename, 'a') as fh:
            fh.write(message)

    def display(self, message):
        super().display(message)
        self.log(message)


class MySubClass(LoggerMixin, Displayer):
    def log(self, message):
        super().log(message, filename='subclasslog.txt')


subclass = MySubClass()
subclass.display("This string will be shown and logged in subclasslog.txt")

python支持多重继承和多继承,且有自己独特的特性。

MRO全称方法解析顺序(Method Resolution Order),在多重继承和多继承存在的时候,寻找属性及方法的顺序。

上例中,MySubClass继承了两个父类LoggerMixin和Displayer。

Mixin是一种设计模式,Mixin类不能单独存在,上例中的super().display(message),如果没有MySubClass提供的Displayer类,则无法执行。


这两个父类如果存在同名函数的话,将按照参数表从左到右的优先级顺序确定执行的函数。

PS:C++遇到这种情况则必须显式指定使用哪个父类的函数。

graph TB D(D) -->B(B) D(D) -->C(C) B(B) -->A(A) C(C) -->A(A)

上例如果使用深度优先的算法,C重载了D的一个方法,会导致搜索不到C的重载,只会用到D。

graph TB D(D) -->B(B) E(E) -->C(C) B(B) -->A(A) C(C) -->A(A)

上例C和D有同名方法,正常应该使用D的方法(D,B应为一个整体,B的优先级比C高),但是如果广度优先就会使用到C的方法。

python3的mro使用c3 linearization算法来解决上述问题。

https://www.cnblogs.com/Hellowshuo/p/16111678.html

c3 linearization详解

命令行参数

-v: 打印运行信息。

-u: stdout立即输出,无缓冲。

deep copy

https://blog.csdn.net/qq_32907349/article/details/52190796

Python的进阶:copy()与deepcopy()区别

https://mp.weixin.qq.com/s/bgk375-KxF-is5dIgV_p4g

5张图彻底理解Python中的浅拷贝与深拷贝

six

six是一个专门用来兼容Python 2和Python 3的库。它解决了诸如urllib的部分方法不兼容,str和bytes类型不兼容等“知名”问题。2x3=6?这难道就是得名的原因?

代码:

https://bitbucket.org/gutworth/six

文档:

https://bitbucket.org/gutworth/six

Python 2 to Python 3

https://www.linuxzen.com/qian-yi-dao-python-3.html

迁移到Python 3

https://www.zhihu.com/question/19698598

Python 2和Python 3有哪些主要区别?

https://mp.weixin.qq.com/s/Q3cqLuOZDSMOdAjVrCDrtQ

在Python 2.7即将停止支持时,我们为你准备了一份3.x迁移指南

https://mp.weixin.qq.com/s/J4bBvu9z3BNcwMSmmL5SMQ

Python 2大限来了!113天后自生自灭,官方不再维护更新

文件print:

Python2: print >>sys.stderr, "fatal error"
Python3: print("fatal error", file=sys.stderr)

dict切片:

Python2: 
self._layers = net.blobs.keys()
self._layers = self._layers[1:] # TypeError: 'dict_keys' object is not subscriptable

Python3:
self._layers = list(net.blobs.keys())
self._layers = self._layers[1:]

检查某对象是否为字符串或Unicode对象:

Python2: isinstance(anobj, basestring)
Python3: isinstance(anobj, str)

range & xrange

1.range会直接生成一个list对象。

2.xrange则不会直接生成一个list,而是每次调用返回其中的一个值。

所以xrange做循环的性能比range好,尤其是返回很大的时候,尽量用xrange吧,除非你是要返回一个列表。

Python 3只有range,效果和Python 2的xrange相仿,且支持slicing。

参考:

http://www.cnblogs.com/zhangjing0502/archive/2012/05/16/2503880.html

Python的range和xrange

enum

class QuantType(Enum):
    FP16 = auto()

auto函数用于自动分配枚举成员的值。

>>>member = Color.RED
>>>member.name
'RED'
>>>member.value
1
>>>Color['RED']
1

Enum默认有name和value两个属性。

enumerate

普通Iterator:

for item in enumerate(list):
    print(item)

带index的Iterator:

for index, item in enumerate(list):
    print(index, item)

for - else

for i in [1,2,3,4]:
    if i > 2:
        print(i)
else:
    print(i, '我是else')

dataclasses

dataclasses是python3.7引入的标准库模块。

from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float

# 创建对象
point = Point(x=1.0, y=2.5)

@dataclass
class FCConfig:
    min_k: int = 512

@dataclass
class BlockConfig:
    fc_config: FCConfig = field(default_factory=FCConfig)

上例中展示了dataclass的基本用法,以及dataclass嵌套的情况下,如何使用默认值,而不是参数,初始化对象。

三元表达式

print('y是一个负数' if y < 0 else 'y是一个非负数')

时间、日期数据的格式处理

时间数据上的格式处理,主要指strftime和strptime函数。其中前者可将时间数据转换成指定格式的字符串,而后者则将字符串转换成时间数据。

import time
a = "2013-10-10 23:40:00"
timeArray = time.strptime(a, "%Y-%m-%d %H:%M:%S")
otherStyleTime = time.strftime("%Y/%m/%d %H:%M:%S", timeArray)

日期方面也是类似的做法。

星期处理

datetime(2002, 12, 4).isoweekday() == 3

datetime(2001, 12, 31).isocalendar() == (2002, 1, 1)#(year, week number, weekday)

从上面的例子还可以看出,isocalendar可以完美的处理跨年问题。

eval

eval函数用来执行一个字符串表达式,并返回表达式的值。

示例:

eval('pow(2,2)')

粗看起来,eval函数在上面的例子中有些多此一举。然而如果字符串来自外部的话,就完全不同了。我们完全可以在任何地方嵌入python脚本。然后,只需要在用到的时候,找到并加载该字符串即可。

argparse

https://blog.csdn.net/It_way/article/details/44815141

python 命令行参数解析 argparse简单分析

pickle

pickle提供了一个简单的持久化功能。可以将对象以文件(后缀名一般为*.pkl)的形式存放在磁盘上。

参考:

https://blog.csdn.net/sinat_29552923/article/details/70833455

Python pickle模块学习


pickle的反序列化存在安全漏洞:

https://www.zhihu.com/question/1296528119

字节跳动大模型训练被实习生恶意注入破坏代码,涉事者已被辞退,攻击带来的影响有多大?

https://zhuanlan.zhihu.com/p/89132768

从零开始python反序列化攻击:pickle原理解析 & 不用reduce的RCE姿势

dill

dill是pickle的威力加强版。

除了提供pickle的功能之外,还可浏览对象的源代码。

示例:

dill.source.getsource(func)

Fork me on GitHub