2017年10月

首页2017年10月
30
Oct
0

动态获取行号,函数名,和函数参数

  1. 获取函数和当前行号

    sys._getframe().f_code.co_name
    sys._getframe().f_lineno
    

2.获取函数参数

import inspect
def a(a, b=0, *c, d, e=1, **f):
    pass
aa = inspect.signature(a)
print("inspect.signature(fn)是:%s" % aa)
print("inspect.signature(fn)的类型:%s" % (type(aa)))
print("\n")
bb = aa.parameters
print("signature.paramerters属性是:%s" % bb)
print("ignature.paramerters属性的类型是%s" % type(bb))
print("\n")
for cc, dd in bb.items():
    print("mappingproxy.items()返回的两个值分别是:%s和%s" % (cc, dd))
    print("mappingproxy.items()返回的两个值的类型分别是:%s和%s" % (type(cc), type(dd)))
    print("\n")
    ee = dd.kind
    print("Parameter.kind属性是:%s" % ee)
    print("Parameter.kind属性的类型是:%s" % type(ee))
    print("\n")
    gg = dd.default
    print("Parameter.default的值是: %s" % gg)
    print("Parameter.default的属性是: %s" % type(gg))
    print("\n")
ff = inspect.Parameter.KEYWORD_ONLY
print("inspect.Parameter.KEYWORD_ONLY的值是:%s" % ff)
print("inspect.Parameter.KEYWORD_ONLY的类型是:%s" % type(ff))

输出结果

inspect.signature(fn)是:(a, b=0, *c, d, e=1, **f)
inspect.signature(fn)的类型:<class 'inspect.Signature'>

signature.paramerters属性是:OrderedDict([('a', <Parameter "a">), ('b', <Parameter "b=0">), ('c', <Parameter "*c">), ('d', <Parameter "d">), ('e', <Parameter "e=1">), ('f', <Parameter "**f">)])
ignature.paramerters属性的类型是<class 'mappingproxy'>

mappingproxy.items()返回的两个值分别是:a和a
mappingproxy.items()返回的两个值的类型分别是:<class 'str'>和<class 'inspect.Parameter'>

Parameter.kind属性是:POSITIONAL_OR_KEYWORD
Parameter.kind属性的类型是:<enum '_ParameterKind'>

Parameter.default的值是: <class 'inspect._empty'>
Parameter.default的属性是: <class 'type'>

mappingproxy.items()返回的两个值分别是:b和b=0
mappingproxy.items()返回的两个值的类型分别是:<class 'str'>和<class 'inspect.Parameter'>

Parameter.kind属性是:POSITIONAL_OR_KEYWORD
Parameter.kind属性的类型是:<enum '_ParameterKind'>

Parameter.default的值是: 0
Parameter.default的属性是: <class 'int'>

mappingproxy.items()返回的两个值分别是:c和*c
mappingproxy.items()返回的两个值的类型分别是:<class 'str'>和<class 'inspect.Parameter'>

Parameter.kind属性是:VAR_POSITIONAL
Parameter.kind属性的类型是:<enum '_ParameterKind'>

Parameter.default的值是: <class 'inspect._empty'>
Parameter.default的属性是: <class 'type'>

mappingproxy.items()返回的两个值分别是:d和d
mappingproxy.items()返回的两个值的类型分别是:<class 'str'>和<class 'inspect.Parameter'>

Parameter.kind属性是:KEYWORD_ONLY
Parameter.kind属性的类型是:<enum '_ParameterKind'>

Parameter.default的值是: <class 'inspect._empty'>
Parameter.default的属性是: <class 'type'>

mappingproxy.items()返回的两个值分别是:e和e=1
mappingproxy.items()返回的两个值的类型分别是:<class 'str'>和<class 'inspect.Parameter'>

Parameter.kind属性是:KEYWORD_ONLY
Parameter.kind属性的类型是:<enum '_ParameterKind'>

Parameter.default的值是: 1
Parameter.default的属性是: <class 'int'>

mappingproxy.items()返回的两个值分别是:f和**f
mappingproxy.items()返回的两个值的类型分别是:<class 'str'>和<class 'inspect.Parameter'>

Parameter.kind属性是:VAR_KEYWORD
Parameter.kind属性的类型是:<enum '_ParameterKind'>

Parameter.default的值是: <class 'inspect._empty'>
Parameter.default的属性是: <class 'type'>

inspect.Parameter.KEYWORD_ONLY的值是:KEYWORD_ONLY
inspect.Parameter.KEYWORD_ONLY的类型是:<enum '_ParameterKind'>
27
Oct
0

为函数动态添加装饰器和参数类型检查

  1. 动态添加装饰器 这里需要用到元编程

    import types
    def decorator_all_function(func):

    def ff(*args):
        print(func.__name__)
        func(args)
    return ff

    class DecoratorMetaClass(type):

    def __new__(cls, clsname, bases, dct):
        ndict = {}
        for name, val in dct.items():
            if isinstance(val,types.FunctionType):
                ndict[name] = decorator_all_function(dct[name])
            else:
                ndict[name] = dct[name]
        return super(DecoratorMetaClass, cls).__new__(cls, clsname, bases, ndict)
    
  2. 测试动态装饰器是否有效

    class BaseClass(object, metaclass=DecoratorMetaClass):

    def get(self):
        print('Hello get')

    class Put(BaseClass):

    def put(self):
        print('Hello put')

    m = Put()
    m.put()
    m.get()

    得到结果

    put
    Hello put
    get
    Hello get

ps.
如果想对每个类都添加,则可以使用__metaclass__ = DecoratorMetaClass

  1. 为了对传入参数进行类型检查而实现的类似其它语言的静态数据类型

    def type_limit(typeLimit,*returnType):

    def test_value_type(func):
        def wrapper(*param,**kw):
            length = len(typeLimit)
            if length != len(param):
                raise LimitError("The list of typeLimit and param must have the same length")
            for index in range(length):
                t = typeLimit[index]
                p = param[index]
                if not isinstance(p,t):
                    raise LimitError("The param %s should be %s,but it's %s now!"%(str(p),type(t()),type(p)))  
            res = func(*param,**kw)
            if "returnType" in returnType:
                limit = returnType["returnType"]
                if  not isinstance(res,limit):
                    raise LimitError("This function must return a value that is %s,but now it's %s"%(limit,type(res) ) )
            return res
        return wrapper
    return test_value_type
    
  2. 使用方法

    @type_limit(int,int)
    def test(x,y):

    return x+y
23
Oct
0

python和shell变量互相传值 命令行输出结果获取

  1. python -> shell:
  2. 设置法 可以正常存取字符串

    import os
    var=123
    os.environ['var']=str(var) #environ的键值必须是字符串
    os.system('echo $var') #print 123

  3. 从通道设置,比如,统计字符数

    import os
    var='var = aabbcc'
    os.popen('wc -c', 'w').write(var)
    os.system('echo $var') # print 12

  4. shell -> python: 直接获取命令行输出

    import os
    var=os.popen('echo -n 123').read()
    print(var)

ps.python命令行两个函数 os.system os.popen 分别为前者获取执行结束后的返回值 后者可以拿到所有的命令输出

17
Oct
0

排序插入单元bisect 及列表内存分配公式

bisect是一个用于对数组进行排序插入的单元,就是排好要插入的数据位置,再插入数据

有如下成员:
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'bisect', 'bisect_left', 'bisect_right', 'insort', 'insort_left', 'insort_right']

如有列表
data = [7,9,4,2,30]

1.insort成员:

插入一个6

bisect.insort(data,6)

返回

[7, 9, 4, 2, 6, 30]

说明它不对源数据进行排序
所以源数据,需要data.sort(),先进行一次排序

2.预插入函数:'bisect', 'bisect_left', 'bisect_right

假如要插入15

i = bisect.bisect(data,15)
print(i) # i = 5
代表插入的15会被放在下标为5的地方,但是data值仍然为[2, 4, 6, 7, 9, 30],所以并没有真的放进去
'bisect_left', 'bisect_right:分别为假如15是会重复的情况下,把15前在左边还是右边,并返回下标,
但在实际结果中看不出什么区别,但如果有其它,比如属性要求的情况下,就有很大的作用了
i = bisect.bisect(data,15)

  1. 'insort', 'insort_left', 'insort_right' 分别对应上面三个预插入函数,但插入时不返回下标
    如:

bisect.insort(data,6)
返回None

当列表新增需要增加大小时会产生复制导致效率低下
列表的内存分配公式 M = (N >> 3) + (N: < 9 ? 3 :6)

N 0 1-4 5-8 9-16 17-25 26-35 36-46 ... 991-1120

M 0 4 8 16 25 35 46 1120

字典和集合默认大小为8 每次改变大小时增加到原来的4倍 达到50000个元素后每次为原来的2倍
在删除时可能会变小 但只发生在插入时
8 32 128 512 2048 8192 32768 131072 262144

数字 int 和 float散列值是它们的数字比特值 字符串元组是基于他们的内容
自定义类通过默认 __hash__得到内建id函数返回内存中的位置 __cmp__比较也是内存位置的数字值

散列碰撞 导致不相等
自定义类判断类实例是否相等
def __eq__(self,other):
return self.x == other.x and self.y == other.y

12
Oct
0

完全支持UTF-8的AES算法

需要先安装包
pip3 install pycrypto

直接上代码 key 必须16位 24位 32位 目前16位够用

def encrypt_aes(s,key):
    cryptor = AES.new(key, AES.MODE_CBC, key)
    text = s.encode("utf-8")
    # 这里密钥key 长度必须为16(AES-128)、24(AES-192)、或32(AES-256)Bytes 长度.目前AES-128足够用
    length = 16
    count = len(text)
    add = length - (count % length)
    text = text + (b'\0' * add)
    ciphertext = cryptor.encrypt(text)
    return b2a_hex(ciphertext).decode("ASCII")

def decrypt_aes(s,key):
    cryptor = AES.new(key, AES.MODE_CBC, key)
    plain_text = cryptor.decrypt(a2b_hex(s))
    return plain_text.rstrip(b'\0').decode("utf-8")