编码格式
decodeURIComponent("%E6%B8%B8%E5%AE%A2")
//"游客"
encodeURIComponent('游客') //
"%E6%B8%B8%E5%AE%A2"
偏函数
>>> int('12345', base=8)
5349
>>> int('12345', 16)
74565
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85
简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,
调用这个新函数会更简单。
注意到上面的新的int2函数,仅仅是把base参数重新设定默认值为2,但也可以在函数调用时传入其他值:
kw = { 'base': 2 }
int('10010', **kw)相当于
int2 = functools.partial(int, base=2)
int2('10010')
python 面向对象
一个小例子
class student(object):
# """docstring for ClassName"""
def __init__(self, name, score):
# super(ClassName, self).__init__()
self.name = name
self.score = score
def print_score(self):
print('%s: %s' % (self.name,self.score) )
bart = student('Bart Simpson', 59)
lisa = student('Lisa Simpson', 87)
bart.print_score() #Bart Simpson: 59
lisa.print_score() #Lisa Simpson: 87
仍以Student类为例,在Python中,定义类是通过class关键字:
class Student(object):
pass
私有变量(优点 因为在方法中,可以对参数做检查,避免传入无效的参数:)
如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,
就变成了一个私有变量(private),只有内部可以访问,外部不能访问,所以,我们把Student类改一改:
class Student(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
def print_score(self):
print('%s: %s' % (self.__name, self.__score))
改完后,对于外部代码来说,没什么变动,但是已经无法从外部访问实例变量.__name和实例变量.__score了:
>>> bart = Student('Bart Simpson', 98)
>>> bart.__name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__name'
你也许会问,原先那种直接通过bart.score = 59也可以修改啊,为什么要定义一个方法大费周折?因为在方法中,
可以对参数做检查,避免传入无效的参数:
class Student(object):
...
def set_score(self, score):
if 0 <= score <= 100:
self.__score = score
else:
raise ValueError('bad score') #报错信息
判断一个变量是否是某个类型可以用isinstance()判断:
>>> isinstance(a, list)
True 例如 判断a是否是list 类型
继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,
也可以把父类不适合的方法覆盖重写。
判断类型 type()
>>> type(123)==type(456)
True
>>> type(123)==int
True
>>> type('abc')==type('123')
True
>>> type('abc')==str
True
>>> type('abc')==type(123)
False
判断函数用可以使用types模块中定义的常量:
>>> import types
>>> def fn():
... pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True
判断继承关系
对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用isinstance()函数。
我们回顾上次的例子,如果继承关系是:
object -> Animal -> Dog -> Husky
那么,isinstance()就可以告诉我们,一个对象是否是某种类型。先创建3种类型的对象:
>>> a = Animal()
>>> d = Dog()
>>> h = Husky()
然后,判断:
>>> isinstance(h, Husky)
True
没有问题,因为h变量指向的就是Husky对象。
再判断:
>>> isinstance(h, Dog)
True
****** @property ******* @score.setter 把方法当属性用
class Student(object):
@property
def score(self):
return self._score
@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
@property的实现比较复杂,我们先考察如何使用。把一个getter方法变成属性,只需要加上@property就可以了,
此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,
我们就拥有一个可控的属性操作:
>>> s = Student()
>>> s.score = 60 # OK,实际转化为s.set_score(60)
>>> s.score # OK,实际转化为s.get_score()
60
>>> s.score = 9999
Traceback (most recent call last):
...
ValueError: score must between 0 ~ 100!
with open('/path/to/file', 'r') as f:
print(f.read()) #读文件
调用read()会一次性读取文件的全部内容,如果文件有10G,内存就爆了,所以,要保险起见,可以反复调用read(size)方法,
每次最多读取size个字节的内容。另外,调用readline()可以每次读取一行内容,调用readlines()一次读取所有内容并按行返回list。
因此,要根据需要决定怎么调用。
如果文件很小,read()一次性读取最方便;如果不能确定文件大小,反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便。
最后一步是调用close()方法关闭文件。文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,
并且操作系统同一时间能打开的文件数量也是有限的
Python引入了with语句来自动帮我们调用close()方法
with open('/path/to/file', 'r') as f:
print(f.read())
写文件的时候把read改成write就行了 r改成w 。
很多时候,数据读写不一定是文件,也可以在内存中读写。
StringIO顾名思义就是在内存中读写str。
要把str写入StringIO,我们需要先创建一个StringIO,然后,像文件一样写入即可:
>>> from io import StringIO
>>> f = StringIO()
>>> f.write('hello')
5
>>> f.write(' ')
1
>>> f.write('world!')
6
>>> print(f.getvalue())
hello world!
Python strip() 方法用于移除字符串头尾指定的字符(默认为空格)。
>>> from io import BytesIO
>>> f = BytesIO()
>>> f.write('中文'.encode('utf-8'))
6
>>> print(f.getvalue())
b'\xe4\xb8\xad\xe6\x96\x87'
StringIO和BytesIO是在内存中操作str和bytes的方法,使得和读写文件具有一致的接口。
dumps()方法返回一个str,内容就是标准的JSON
用loads()或者对应的load()方法,前者把JSON的字符串反序列化
>>> import json
>>> d = dict(name='Bob', age=20, score=88)
>>> json.dumps(d)
'{"age": 20, "score": 88, "name": "Bob"}'
>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> json.loads(json_str)
{'age': 20, 'score': 88, 'name': 'Bob'}
import json #导入python 中的json模块
l = ['iplaypython',[1,2,3], {'name':'xiaoming'}]
#创建一个列表list l
encoded_json = json.dumps(l)
# 将l列表,进行json格式化编码
print(repr(l))#['iplaypython', [1, 2, 3], {'name': 'xiaoming'}]
print (encoded_json) #["iplaypython", [1, 2, 3], {"name": "xiaoming"}]
线程是最小的执行单元,而进程由至少一个线程组成。
import os
print('Process (%s) start...' % os.getpid())
# Only works on Unix/Linux/Mac:
pid = os.fork()
if pid == 0:
print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid()))
else:
print('I (%s) just created a child process (%s).' % (os.getpid(), pid))
Process (876) start...
I (876) just created a child process (877).
Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()调用一次,
返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。
子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,
而子进程只需要调用getppid()就可以拿到父进程的ID。I am child process (877) and my parent is 87
# 子进程要执行的代码
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.')
执行结果如下:
Parent process 928.
Child Process will start.
Run child process test (929)...
Child Process end.
如果没join
执行结果如下:
Parent process 10724.
Child process will start.
Child process end.
Run child process test (8736)...
创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process实例,用start()方法启动,这样创建进程比fork()还要简单。
join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步
python常用内置模块
1.datetime (datetime是Python处理日期和时间的标准库)
from datetime import datetime
now = datetime.now() # 获取当前datetime
print(now)
print(type(now))
@contextmanager
def tag(name):
print("<%s>" % name)
yield
print("</%s>" % name)
with tag("h1"):
print("hello")
print("world")
上述代码执行结果为:
<h1>
hello
world
</h1>
代码的执行顺序是:
with语句首先执行yield之前的语句,因此打印出<h1>;
yield调用会执行with语句内部的所有语句,因此打印出hello和world;
最后执行yield之后的语句,打印出</h1>。
因此,@contextmanager让我们通过编写generator来简化上下文管理