各大模块
api.py
- 里面定义常用的方法例如: 各种请求方式get,post,post,put…,调用之后他们返回的都是一个Request对象
ps: 在get,option方法中都有kwargs.setdefault(‘allow_redirects’, False),这也就意味着如果我们调用方法不传入allow_redirects,那么requests包就会默认帮我们设置为允许重定向
单个get函数如下:
def get(url, params=None, **kwargs):
r"""Sends a GET request.
:param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary, list of tuples or bytes to send
in the body of the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
"""
kwargs.setdefault('allow_redirects', True)
return request('get', url, params=params, **kwargs)
- Request对象, 注释写的很详细
1,**kwargs中会拿到所有传参,以上get请求中的params相当于是针对不同请求类型进行设定,而**kwargs中的参数是针对所有请求类型
2, 随后用with语句打开了一个session对象
def request(method, url, **kwargs):
# By using the 'with' statement we are sure the session is closed, thus we
# avoid leaving sockets open which can trigger a ResourceWarning in some
# cases, and look like a memory leak in others.
with sessions.Session() as session:
return session.request(method=method, url=url, **kwargs)
session.py
class Session 对象
- session 注释中写出了,session提供三个功能,cookie的持久化,连接池和配置文件
- __attrs__ = […] 这里面就写出了一堆session对象所拥有的属性
- 我曾以为底层是封装的urllib2。。。。结果发现是针对 urllib3 的内置 HTTP Adapter,通过实现传输适配器接口,为 session 和 HTTP、 HTTPS连接提供了一个通用的接口。该类的实例通常由内部包裹下的Session类创建。
- 看到了在对于session连接池中,默认最大的连接池数量是DEFAULT_POOLSIZE = 10
优雅的的代码:
# 感觉这样写代码很优雅=-=
# Default empty dicts for dict params.
data = [] if data is None else data
files = [] if files is None else files
# __slot__ 用法,个人理解如下
优点以及原因:
1, Python会把对象的属性储存到一个字典中,所以当你创建很多对象(百万级别的时候才值得用《流畅的Python》)会占用很多内存,而利用__slot__魔法方法则可以节省接近一半的内存
缺点:
1. 每个继承的子类都要重新定义一遍__slots__
2. 实例只能包含哪些在__slots__定义的属性,这对写程序的灵活性有影响,比如你由于某个原因新网给instance设置一个新的属性,比如instance.a = 1, 但是由于a不在__slots__里面就直接报错了,你得不断地去修改__slots__或者用其他方法迂回的解决
3. 实例不能有弱引用(weakref)目标,否则要记得把__weakref__放进__slots__
参考链接:http://book.pythontips.com/en/latest/__slots__magic.html
# 整个包里面会出现很多这种情况,就是类型判断isinstance(感觉Python平时都是各种类型满天飞。。。。)
if isinstance(params, (str, bytes)):
params = to_native_string(params)
# @property
class Celsius:
def __init__(self, temperature = 0):
self.temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
def get_temperature(self):
print("Getting value")
return self._temperature
def set_temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self._temperature = value
#temperature = property(get_temperature,set_temperature)
在response类中可以看到很多关于这个类的属性,就是用到了property装饰器进行装饰
个人理解:
1, 被装饰的是属于对象的一个属性,而不是动态方法
2, 以上代码存在可以把self.temperature属性设置成其他类型的问题比如:
Celsius().temperature = "2"
当然我们可以在set_temperature()中对类型进行限制,不过要知道如果之前有很多包调用了这个类,且用的是Cesius().temperature= x ,那相当于set_temperature中的代码是没有生效的。。。。,而你想要他生效还要去之前所有引用的地方代码进行修改。另外,你不能保证后面的人写代码不会直接.temperature=x这样赋值
详解链接:https://www.programiz.com/python-programming/property
models.py
-
定义了各种对象的方法和属性设置之类的
优雅的代码:#对于一些全局的常量就用过全大写 REDIRECT_STATI = ( codes.moved, # 301 codes.found, # 302 codes.other, # 303 codes.temporary_redirect, # 307 codes.permanent_redirect, # 308 ) DEFAULT_REDIRECT_LIMIT = 30 CONTENT_CHUNK_SIZE = 10 * 1024 ITER_CHUNK_SIZE = 512 # 属性操作 hasattr(fp, 'read') # 判断某个对象是否有read属性 setattr(fp, 'read') # 给对象设置read属性 getattr(foo, 'bar')() # 可以通过字符串调用对象的方法
收获
- 1,优雅代码的写法,比如常量大写,一些变量定义可以一行if else搞定,@property的用法
- 2,注释的写法,注释一定要给力,这样可以省去很多维护成本
- 3,一些魔法方法__bool__,slot…
- 4,传说中的退火算法
- 5,有事没事多看源码,英语ok的话,啃着注释和readme.md就可以搞定,另外Google是个好东西