Python知识点梳理

Python是这两年比较火的一门语言,上手容易,代码可读性高,在web开发尤其是机器学习领域内得到很广泛的应用。

我自己半年前也学过Python,当时写了几个网络爬虫,由于长时间不用,现在好多东西都忘记了,这两天抽空回顾了Python。这里整理了下感觉重要的一些知识点。

  1. Python解释器由于设计时有GIL全局锁,导致了多线程无法利用多核。多线程的并发在Python中就是一个美丽的梦。

  2. Python 是一种解释型语言,类似于Java,其实际上是字节编译的,其结果是可以生成一种近似于机器语言的中间形式
    ,改善了其性能并保持了解释型语言的优点。

  3. print(str,end=’’)加上end=’’,可使其不自动换行。

  4. init可以被当成构造器,不过不像其它语言中的构造器,它并不创建实例–它仅仅对象创造后执行的第一个方法,执行
    一些必要的初始化工作。

  5. Python的多元赋值方式可以实现无需中间变量交换两个变量的值。

1
2
x, y = 1, 2
x, y = y, x
  1. 变量名_xxx被看作是私有的,在模块或类外不可用

  2. 将经常用到的模块属性替换为一个本地引用,代码运行得更快,而也不用敲那么长的变量名了。

1
ls = os.linesep
  1. 所有类型对象的类型都是type,它也是所有Python类型的根和所有Python标准类的默认元类(metaclass)。

  2. Python 提供了is 和 is not操作符来测试两个变量是否指向同一个对象。a is b 等价于 id(a) == id(b)

  3. Python 仅缓存简单整型,它认为Python应用程序中这些小整数型会经常用。(Python 3.5.0 范围是-5~256)

  4. str()函数得到的字符串可读性较好,而repr()函数得到的字符串通常可以用来重新获得该对象,通常情况下

1
Obj == eval(repr(obj)。
  1. 比较对象类型时,最好不要使用type(2) == type(0)这样的代码,应该减少函数调用的次数,导入types模块,然后使用如下:
1
2
3
4
>>>type(2) == int
>>>type(2.0) == float
>>>type([]) == list
>>>type(False) == bool
  1. Python的长整型类型能表达的数值仅仅与本地机器支持的(虚拟)内存大小有关,可以轻松表达很大的值。要用大写字
    母“L”表示长整型。

  2. abs()返回给定参数的绝对值,如果参数是一个复数,那就返回math.sqr(num.real + num.imag)。

  3. chr()接受一个单字节的整型值,返回一个字符串,其值为对应的字符。函数ord()则相反,它接受一个字符,返回其对应的整型值。

  4. Python中布尔型是整型的子类,但是不能再被继承而生成其它的子类。没有nonzero()(Python 3.x为 bool())
    的方法的对象默认值是True.对于值为零的任何数字或空集(空列表、空元组和空字典等)在Python中的布尔值都是False.

  5. split()把string切片成一个列表,用join()方法可以把这个列表重新连接成一个字符串。

1
2
3
>>>quest = 'what is your favorite color'
>>>':'.join(quest.split())
'what:is:your:favorite:color'
  1. 所有函数返回多对象(不包括有符号封装的)都是元组类型。tuple = (1,) 创建只有一个元素的元组。

  2. 非容器类型(比如数字、字符串和其他‘原子’类型的对象,像代码、类型和range对象等)没有被拷贝一说,浅拷贝是完全用切片操作来完成的。如果元组变量只包含原子类型,对它的深拷贝将不会进行。下面是一个深拷贝的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> import copy
>>> person = ['name',['savings',100]]
>>> hubby = person
>>> wifey = copy.deepcopy(person)
>>> [id(x) for x in (person, hubby, wifey)]
[2287513851656, 2287513851656, 2287513851528]
>>> hubby[0] ='jim'
>>> wifey[0] ='tom'
>>> hubby,wifey
(['jim', ['savings', 100]], ['tom', ['savings', 100]])
>>> hubby[1][1] = 50
>>> hubby, wifey
(['jim', ['savings', 50]], ['tom', ['savings', 100]])

20.内建函数sorted()通过输入一个字典参数返回一个有序的迭代子。

1
2
3
>>> dict1 = {'e':4,'b':2,'a':1}
>>> sorted(dict1)
['a', 'b', 'e']
  1. 可以把每行分割为单词,然后计算单词的个数:
1
2
>>> f = open('sample.txt', 'r')
>>> len([word for line in f for word in line.split()])
  1. SyntaxError异常是唯一不是在运行时发生的异常。

  2. 用try-except语句捕获AssertionError异常:

1
2
3
4
5
6
7
>>>try :
assert 1 ==0, 'One does not eaqual zero silly!'
except AssertionError as args:
print('%s: %s' % (args.__class__.__name__, args))
AssertionError: One does not eaqual zero silly!
  1. 偏函数
1
2
3
4
5
6
7
8
>>> from operator import add
>>> from functools import partial
>>> add1 = partial(add, 1)
>>> add1(3)
4
>>> baseTwo = partial(int, base=2)
>>> baseTwo('100100')
36
  1. 静态方法和类方法,实例方法隐含的参数为类实例,而类方法隐含的参数为类本身。静态方法无隐含参数,主要为了类实例也可以直接调用静态方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class A(object):
"This ia A Class"
@staticmethod
def Foo1():
print("Call static method foo1()\n")
@classmethod
def Foo2(cls):
print("Call class method foo2()")
print("cls.__name__ is ",cls.__name__)
A.Foo1();
A.Foo2();
Call static method foo1()
Call class method foo2()
cls.__name__ is A
  1. 运算符重载 add()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class data():
def __init__(self, val):
self.val = val
def __add__(self, other):
return data(self.val + other.val)
def __str__(self):
return str(self.val)
__repr__ = __str__
>>> a = data(2)
>>> b = data(3)
>>> a+b
5

27.授权是包装的一个特性,可用于简化处理相关命令性功能,采用已存在的功能以达到最大限度的代码重用。包装一个类型通常是对已存在的类型的一些定制。实现授权的关键点就是覆盖getattr()方法,在代码中包含一个对getattr()内建函数的调用。特殊行为没有在类型方法列表中,不能被访问,因为它们不是属性,如切片。实现一个包装类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
>>> class WrapMe:
def __init__(self, obj):
self.__data = obj
def get(self):
return self.__data
def __repr__(self):
return str(self.__data)
def __str__(self):
return str(self.__data)
def __getattr__(self, attr):
return getattr(self.__data, attr)
>>> wrap = WrapMe(3.5 + 2j)
>>> wrap
(3.5+2j)
>>> wrap.real
3.5
>>> wrap.imag
2.0
>>> wrap.conjugate()
(3.5-2j)
>>> wrap.get()
(3.5+2j)
  1. slots是一个类变量,由一序列对象组成,由所有合法标识构成的实例属性的集合来表示。它可以是一个列表,元组或可迭代对象,也可以是标识实例能拥有的唯一的属性的简单字符串。任何创建一个其名不在slots中的名字的实例属性都将导致AttributeError异常。

主要目的是节约内存,防止用户随心所欲地增加实例属性。带slots属性的类定义不会存在dict中,除非在slots中增加dict的元素。

1
2
3
4
5
6
7
8
9
10
11
class SlottedClass:
__slots__ ={'foo', 'bar'}
>>> c = SlottedClass()
>>> c.foo = 42
>>> c.xx = 'WTF'
Traceback (most recent call last):
File "<pyshell#253>", line 1, in <module>
c.xx = 'WTF'
AttributeError: 'SlottedClass' object has no attribute 'xx'
  1. Python给类提供了call的特别方法,该方法允许程序员创建可调用的对象(实例),默认情况下,call方法是没有实现。意味着大多实例是不可调用的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> class C:
def __call__(self, *args):
print(" I'm callable! Called with args:\n", args)
>>> c = C()
>>> c
<__main__.C object at 0x000002149A744C88>
>>> c()
I'm callable! Called with args:
()
>>> c(3)
I'm callable! Called with args:
(3,)
>>> callable(c)
True
  1. compile()可用来动态生成字符串形式的Python代码,然后生成一个代码对象。 第一个参数是字符串,第二个参数通常置空,其代表了存放代码对象的名字(字符串类型),第三个参数如下:
  • ‘eval’ ,可求值的表达式[和eval()一起使用]
  • ‘single’ , 单一执行语句[和exec一起使用]
  • ‘exec’ ,可执行语句组[和exec一起使用]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> eval_code= compile('100 + 200', '', 'eval' )
>>> eval(eval_code)
300
>>> single_code = compile('print("Hello world!")', '', 'single')
>>> exec(single_code)
Hello world!
>>> exec_code = compile('''
req = input("input the numbers:")
for eachnum in range(int(req)):
print(eachnum)
''', '', 'exec')
>>>
>>> exec(exec_code)
input the numbers:3
0
1
2
  1. sub()和subn()完成搜索和代替的功能,后者还能多返回一个表示替换次数的数字。
1
2
3
4
>>> re.sub('jim', 'xxxx', 'jim is a fucking guy.')
'xxxx is a fucking guy.'
>>> re.subn('jim', 'xxxx', 'jim is a fucking guy')
('xxxx is a fucking guy', 1)
  1. Python3.x 中TCP/UDP 接收和发送的数据要编码和解码(encode()和decode())。

  2. 对Python虚拟机的访问由全局解释器锁(global interpreter lock,GIL)来控制,正是这个锁能保证同一时刻只有一个线程运行。

  3. 守护进程,在调用thread.start()之前,调用setDaemon()函数设定线程的daemon标志(thread.setDaemon(True)),就表示这个线程“不重要”.