python自定义函数调用 apply Python自定义函数调用keyerror_virtualenv


装饰器

一切皆对象

def hi():

pass

# 我们甚⾄可以将⼀个函数赋值给⼀个变量,⽐如

greet = hi

# 删除函数

del hi


def


当你把⼀对⼩括号放在后⾯,这个函数就会执⾏;

然⽽如果你不放括号在它后⾯,那它可以被到处传递,并且可以赋值给别的变量⽽不去执

⾏它。

蓝本规范:


from


@decorator_name

def func():

return("Function is running")

@wraps接受⼀个函数来进⾏装饰,并加⼊了复制函数名称、注释⽂档、参数列表

等等的功能。这可以让我们在装饰器⾥⾯访问在装饰之前的函数的属性。

授权 Authorization

装饰器能有助于检查某个⼈是否被授权去使⽤⼀个web应⽤的端点(endpoint)。它们被⼤量

使⽤于Flask和Django web框架中。这⾥是⼀个例⼦来使⽤基于装饰器的授权:


from functools import wraps
def requires_auth(f):
     @wraps(f)
     def decorated(*args, **kwargs):
         auth = request.authorization
         if not auth or not check_auth(auth.username, auth.password):
             authenticate()
         return f(*args, **kwargs)
     return decorated


多个return值

def profile():

name = "Danny"

age = 30

return name, age

这是一种比列表和字典更好的方式。不要使用global关键字,除非你知道你在做什么。

对象变动 Mutation

在Python中当函数被定义时,默认参数只会运算一次,而不是每次被调用时都会重新运算。

你应该永远不要定义可变类型的默认参数,除非你知道你正在做什么。你应该这样做:

def add_to(element, target=None):

if target is None:

target = []

target.append(element)

return target

__slots__魔法

默认情况下Python用一个字典来保存一个对象的实例属性。这非常有用,因为它允许我们在运行时去设置任意的新属性。

为了节省内存,可以使用__slots__来告诉Python不要使用字典,而且只给一个固定集合的属性分配空间。使用__slots__之后,不可以设置__slots__之外的新属性。


class MyClass(object):
    __slots__ = ['name', 'indentifier']
    def __init__(self, name, indentifier):
        self.name = name
        self.identifier = identifier 
        # self.set_up() ...


测试内存使用 ipython_memory_usage(使用方法待研究)

virtualenv

virtualenv创建独立(隔离)的Python环境

安装:

pip install virtualenv

创建环境

virtualenv myproject

激活

cd myproject

source bin/activate

福利

你可以使⽤smartcd来帮助你管理你的环境,当你切换⽬录时,它可以帮助你激活

(activate)和退出(deactivate)你的virtualenv。我已经⽤了很多次,很喜欢它。

容器 Collections

defualtdict

defaultdict与dict类型不同,你不需要检查key是否存在。

from collections import defaultdict

另一个重要的例子是:当你在一个字典中对一个键进行嵌套赋值时,如果键不存在,会触发keyError异常。defaultdict允许我们用一个聪明的方式绕过这个问题。

问题:

some_dict = {}

some_dict['colours']['favourite'] = "yellow"

## 异常输出:KeyError: 'colours'

解决方案:

import collections

tree = lambda: collections.defaultdict(tree)

some_dict = tree()

some_dict['colours']['favourite'] = "yellow"

## 运行正常

import json

print(json.dumps(some_dict))

## output: {"colours": {"favourite": "yellow"}}

deque

deque提供了一个双端队列,你可以从头/尾两端添加或删除元素。

from colections import deque

namedtuple

你可以像字典一样访问namedtuple,但namedtuple是不可以变的。

from collection import namedtuple

Animal = namedtuple("Animal", "name age type")

perry = Animal(name="perry", age=31, type="cat")

print(perry.name)

namedtuple比字典快

你可以将命名元组转换为字典,方法如下:

print(perry._asdict())

# output OrderDict([("name", "Perry"), ("age", 31),...])

enum.Enum (Python 3.4+)

perry命名元组中type使用了字符串,容易写错,可以使用Enum规范一下,避免使用字符串。

from enum import Enum

class Species(Enum):

cat = 1

dog =2

horse = 3

上面的perry可以改写如下:

# old

# perry = Animal(name="perry", age=31, type="cat")

# new

perry = Animal(name="perry", age=31, type=Species.cat)

对象自省

inspect模块

inspect模块提供了许多有用的函数,来获取活跃对象的信息。

比如说查看一个对象的成员,只需运行:

import inspect

print(inspect.getmembers(str))

推导式

list comprehensions

规范

variable = [out_exp for out_exp in input_list if out_exp ==2]

例子:

mulitiples = [i for i in range(30) if i % 3 is 0]

dict comprehensions

快速对换字典的键和值

{v: k, for k, v in some_dict.items() }

set comprehensions

集合推导式跟列表推导式类似,唯一的区别在于它们使用大括号{}。

squared = {x**2 for x in [1,1,2]}

一行式

计算器:

python3 -c "print(100*200)"

# output 20000

列表展平 itertools.chain.from_iteerable

import itertools

print(list(itertools.chain.from_iteerable(a_list)))

# or

print(list(itertools.chain(*a_list)))

For - Else

for 后面的else会在循环结束时执行,这意思着,循环没有遇到任何break.

for item in container:

if search_something(item):

# Found it

process(item)

break

else:

# Didn't find anything...

not_found_in_container()