Python心得

介绍

用力学。

未解决的问题

什么是eval?

犯过的错误

  • A little important thing to be cautious:

    nums[:] = nums[n-k:] + nums[:n-k]

    can’t be written as:

    nums = nums[n-k:] + nums[:n-k]

    on the OJ.

    The previous one can truly change the value of old nums, but the following one just changes its reference to a new nums not the value of old nums.

  • 在数二进制有多少个1的时候用sum巨慢无比,bin(num)[2:].count(‘1’)是一个更好的选择?

    • 不是吧…如果用 & 的话应该会更快?
  • 对于123456这种连续的改变,只记录1和7然后用cumulative的方式再变回去会快很多

  • 要是对array是否为none做sanity check当然更好。注意这个叫sanity check

== 和 is 的区别: 前面是判断等价关系。后面的is是判断identity,也就是两个内存单元的判断。所以有时候对于class的类别,因为没有默认的等价关系,所以都会默认区比较内存单元,会出现这样的问题:

a, b = ListNode(1), ListNode(1)
print a == b #会返回False,需要class里面 def __eq__(self, other)
#定义了eq就需要再定义两个事情:def __ne__(self, other); def __hash__(self) 哈希值

一般答案的输出集合:Res = [] result的意思

一个已经被decode了的字符s不具有属性s.decode

两个字符串相加,时间复杂度是O(N) 因为后面那个字符需要一个一个添加进去

输入与输出并不算在空间复杂度之中(输出也不算)。

计算递归的复杂度,可以画树状图的方式。关于空间复杂度,不是每一层占用的空间,因为函数调用串行执行,一路走到底才会走到其他分支。所以每一层其实只占用一份的空间,其他要不然已经被释放了,要不然还没走到

#有的时候我会用两个stack倒来倒去,就像这样:
stack1, stack2 = [root], []
while stack1:
    while stack1:
        r = stack1.pop()
        ....
        stack2.append(...)
    stack1, stack2 = stack2, stack1
#今天看到一个老哥的代码:
q = collections.deque([root])
for _ in range(len(q)):
    r = q.popleft()
    q.append(....) #感觉更简洁,并且时间复杂度一样

基础

  • Python 变量命名规则
    • 以下划线/字母开始
    • 字母+数字+下划线 来命名
    • 大小写敏感
    • 存在一些保留字符,如果强行赋值的话会报错,但是有些语言就会同意你来重新赋值
  • Python 2.7里面做的是整数除法【不是四舍五入而是向下取整】但是python3里面是浮点除法
    • 提示:print 1.0 * 5250/1000print 5250/1000 * 1.0 答案不同
  • 变量类别:
    • None 就是NA的意思
    • 很大的整数是long类型的(2**63左右)
    • float(‘inf’) 和 float(’-inf’) 表示无穷【大小写无所谓】
  • raw_input(‘Some Instructions…’) 用户可以输入,默认是字符串。
    • 如果用input的话,会evaluate式子。比如a = input('...'); 1+1 【a被传递了2】
    • 默认是一行,如果多行的话需要加while然后逐行输入
  • 语句块不一定都是一个tab也可以是一个空格,只要大家的缩进都相同。【缩进都缩回去了,所以不需要end】良好的coding习惯可以在代码块的下面空一行
  • 三个单/双引号可以注释代码块,在赋值中也是为了在里面输入单引号&双引号
  • 任何非0和非None都会被evaluate成True。只有【0和None】会被evaluate成False
  • If 0 < 1 : print '能运行 ’ 但是不推荐
  • 逻辑比较:not > and > or 【这个啥意思】
  • 在文件开头加入 # -*- coding: UTF-8 -*- 或者 #coding=utf-8 就可以让python以utf-8进行编码【默认是ASCII】
  • range只能产生整数序列,numpy.arrange可以产生float数列
  • python当print的东西是None的时候,返回的不是空白,而是四个英文字母:None
  • Python is a PASS-BY-OBJECT-REFERENCE programming language
    • 存储分为stack和heap。stack存放的是reference(变量名)。重新赋值(x = [1])的时候stack里面的reference不变,但是指向了heap(存储了object)里面的一个新的个体。扩充赋值[x.append(1)]这时候heap里的数量没多,元素发生了改变。
    • 平时我们说的占用内存是指heap + stack 合起来的大小
    • a = [1], b = a, a =[2] 此时b的值是[1]
    • 【某语言】pass by reference: x = [1] 会变成 x = [1] 重新赋值&改变object都会导致值的改变
    • 【某语言】pass by value: 会把object和reference都copy一遍 x = [1] 会变成 x’ = [1]’ 怎么操作跟原来都没关系。
    • 【Python】pass by object reference: x = [1] 会变成 x’ = [1] 重新赋值不会改变,修改的时候会改变
  • tab 是 increase indent / shift + tab 是decrease indent
  • 空间复杂度:取决于额外产生的空间。因为那些数据占用的地方跟我运行我的程序没关系,并不能用来评估我的这个代码的效率。额外的空间一般都存在内存的heap里面,除了recursion【这里的heap 和stack只是内存的,和另外的heap&stack不是一个东西】
  • ctr+shift+r 运行代码
  • //地板除,%显示余数
  • map支持批量化操作,节省运算速度,不用每一次都解析代码。
  • ord:Return the Unicode code point for a one-character string
  • bin(number)[2:] 可以去掉前面的’0b’
  • elif =else if
  • s.index(max(s)) 返回s中最大值的index
  • 判断list是否是空的:if list/ if not list
  • 在环境中删除变量。del var
  • 关于xrange与range的区别:range(1,n) allocates memory to store all the 1…n values. But xrange(1,n) generates them on the fly: in each iteration the next number is generated. So it is better memory wise.
  • del:删除一个变量-如同他从未存在过
  • print(‘These items are:’, end=’ ‘) end=’'在结尾加上一个空格。默认是换行
  • time.strftime(格式) 打印当前时间 (import time)
  • 程序需要人为换行的时候可以加一个反斜杠’’
  • print("There are {:d} robots".format(Robot)) : :d这里表示了Robot的格式
  • input(‘展示内容’)可以让录入用户输入的信心,返回的数据类型是str,要通过int()来变成整数
  • assert 语句:确信某事是真的,如果是假的,则直接报错返回。便于我们检查错误
  • type函数判断类型
  • id(variable) 可以返回variable所指向的内存地址,以十进制的方式来表示
  • python切片操作是左闭右开
  • reduce() 函数会对参数序列中元素进行累积。函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。

如何保存set到本地

函数

  • 函数是一个动词,执行具体的行为。函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
  • print函数默认以一个回车’\n’结尾。print(‘a’,end = ‘?’)可以修改。print在打印多个对象之间会默认以一个空格连接:sep=’'可以修改
  • for和while循环也可以连接else。显而易见的。else总会被运行,除非for/while中间有break。continue 跳过代码中的剩余部分,进行下一循环
  • 如果想在函数里面使用并修改全局变量,global x,y,… 可以告诉pyhon接下来函数中的用的x是一个全局变量。
  • default直接在定义里面写等于,函数中没有默认值的参数必须放在有默认值的参数的前面
  • 可变参数:函数中输入参数的个数是可变的。使用*加变量名会把传入的数据生成一个tuple,使用**的话则生成一个字典。
  • 如果return没有搭配任何一个值,则表示return None
  • Python 中的 pass 语句用于指示一个没有内容的语句块。
  • print(function._doc_) 可以打印出来function的文档字符串。建议我在编写函数的时候,在函数的第一行就用一对三引号来写一下函数说明
  • 函数只evaluate到return为止,如果return的条件满足了,之后的代码就不会被执行了。return比break更强,break只能跳出一层,return直接跳出所有东西,结束了函数。
  • 函数可以有多个返回值,可以return x,y 赋值的时候a,b = f()
  • 函数传递的时候可以不按照顺序:
    • def f=(name,age)
    • y = f(age = 12, name = 'Jack')
max_idx, max_val = max(enumerate(nums), key=lambda x: x[1]) #可以获得max的index

函数内定义函数:Closure

  • we have a closure in Python when a nested function references a value in its enclosing scope. And The enclosing function must return the nested function.
  • 在python3 里面可以用 nonlocal 来修改

循环

  • continue和break只针对外面的一层,想跳出多层循环的话只能用boolean flag

  • 如果只是用于循环而不需要一个序列的话,用xrange要比range更好。xrange本质上是一个生成器

  • 关于尾递归

字符

  • 字符叫char(character) 字符串叫str(string)
  • '1'*2 = '11';'1'+'2' = '12' 但是除号不能用于 str和int之间。Concatenation
  • 字符串不支持对某个位置进行重新赋值: 字符串是不可变的
  • u’xxxx’ 表示xxx是用unicode来加密的
  • list()将字符串变成列表。’’.join()将列表变成字符串
  • a = ‘word’*5 迅速创建字符
  • b = [ str(i) for i in a ]迅速将数字列表转化为字符列表
  • s.split()可以将字符按照空格切开
  • 判断大小写:str.islower/str.isupper. 大小写互换: str.swapcase()
  • python中大小写转换:str.upper:全部变为大写、str.lower():全部变为小写、str.capitalize()字符串的第一个单词的首字母变为大写,其他都是小写、str.title():字符串的每个单词首字母大写,其他变为小写、
  • 多行字符可用三个单引号或者双引号括起来,甚至可以用’’’’….’’’’ 只要前后引号数量一样即可,毕竟只有单引号双引号这两个可能不够用
  • 虽然加号可以连接多个字符,但这样被认为是不优雅的。‘I am’ + str(age) + ‘years old’ 可以写成:‘I am {0或者空着} years old’.format(age)。format有多种用法: {0:.3f}保留小数点后三位。{0:_^11}使用下划线填充文本使文字在中央,字符长度填充为11位。大括号里面可以什么都不写,也可以写index,也可以写’name’这种具体含义,但是如果写了name需要在format里面变成'My name is {name}'.format(name = 'Siyu')
  • 在字符串的末尾加一个反斜杠’\'表示字符串将在下一行继续,但是不会变成新的一行. 用反斜杠属于显式行连接,用括号连接则属于隐式行连接。
  • 原始字符串:常在正则表达式中出现,前面带一个r或R。前面带一个u表示是unicode编码
  • 对于不可变对象str操作的时候,比如说 a.replace(‘b’, ‘B’) 其实是创建了一个新的字符,新的字符所有的b都变成了B,而a本什么还是没有发生变化
  • 字符串有函数s.index(‘x’),返回x在字符串中的位置
  • x.split(’ ')[index] 可以将以空格分隔的字符拆分成几个,再用index索引取出来
  • str.zfill(num) 可以往字符前面补0来达到固定位数
  • ord: 返回字符的asc码. chr()将asc变成字符
  • chr.startswith() 判断是不是以某个字符串开始。if 'a' in chr 判断’a’是否在chr中,chr.find(xx) 如果xx在chr中则返回下标,如果不在,则返回1. 'xx'.join(List) 将List(字符列表)中的元素用xx连接起来变成一个字符
  • str.find()字符中找匹配字符,找到了返回位置,没找到返回-1
  • 去掉所有标点符号re.sub('[%s]' % re.escape(string.punctuation), '', paragraph)
str.strip()#可以去掉首尾空格

两个字符(长度分别为m, n)拼接操作m+n 时间复杂度是O(m+n)

正则表达式

  • re.findall(r’abc’,s) 从s中找到所有abc并返回abc

Encoding

https://docs.python.org/3/howto/unicode.html #unicode教程

https://www.compart.com/en/unicode/ #unicode查找

"\N{GREEK CAPITAL LETTER DELTA}"  # Using the character name

"\x0394"                          # Using a 8-bit hex value
"\u0394"                          # Using a 16-bit hex value
"\U00000394"                      # Using a 32-bit hex value

字典

  • 当有一列key和一列value的时候,想合成一个dict:d = dict(zip(key,value))
  • 根据value找key:list(dicxx.keys())[list(dicxx.values()).index(“001”)]但是多对一的映射不好写
  • 字典的Key值必须是不可变的对象(比如字符)

M.get(k, d=None): 从字典M里面找key=k,找不到的话返回d而不是报错

M.setdefault(k, d): If key k exists in the map, simply return M[k]; if key k does not exist, set M[k] = d and return that value.

M.pop(k, d=None): Remove the item associated with key k from the map and return its associated value v. If key k is not in the map, return default value d. 正常删除用:del M[k]

M.popitem(): Remove an arbitrary key-value pair from the map, and return a (k,v) tuple representing the removed pair. If map is empty, raise a KeyError.

M.clear(): Remove all key-value pairs from the map.

M.update(M2): Assign M[k] = v for every (k,v) pair in map M2.

集合

  • bric = bri.copy() 集合的硬复制,其他种类的硬复制可以通过切片的方式a[:]
  • 交集运算:bri & bric # OR bri.intersection(bric)差集: 减号或者^。并集用 |

b.issubset(a) 判断b是否是a的子集

数字

  • 52.4E10采用科学计数法,返回一个floats
  • 平方运算是**:3**2=81
  • int(‘num’,base=N) 将N进制的数转换为10进制
  • bin()[2:] 转化为二进制
  • print(’%.4f’ % 1.6) 可以规定输出小数位数

列表List

  • 可变长度的,而其他语言的array都是固定长度的,因此python没有array这个概念…所以对于长度:
    • 开始有个默认长度,比如说10
    • 不断的插入元素,当达到capacity的时候(80%)
    • 创建一个新的list,具有双倍的长度:20
  • list支持mixed type
  • 用加号可以连接多个list
  • lst.extend([xxxx]) 可以同时append多个元素在lst的最后/也可以用加号
  • 可以用del(lst[index]) 来删除固定位置的东西
  • lst.remove(element) 删除第一个出现的element。如果没有出现,则报错
  • 比较两个字符的大小,从第一个不一样的元素开始比较。如果有一个元素走到头了,剩下的长的元素会被认为是大的那个。字符会变成ASCII码来进行比较
  • list的索引从0开始,倒数第n个元素可以用「-n」或「len()-n」做索引
  • 排序可以用lst.sort() 或者sorted(lst) A.sort(key = lambda x: x % 2) 按照除2的余数排序
  • 向list中追加元素:list.append(‘new’)
  • 把元素插入制定的位置:list.insert(num,‘new’)
  • list.pop(n),删除第n个元素,什么都不填的话默认删除最后一个元素
  • 可以通过list[k] = ‘new’ 来直接替换第k个位置上的元素
  • list里面的元素类型可以不同,甚至一个list都可以成为另一个list里面的元素
  • [12,3]*3 答案是[12,3,12,3,12,3] 乘号是重复整个list元素
  • list是mutable可变的,而字符串是不可变的(Immutable)。所以我们可以对list进行sort直接修改源文件,但是不能这么对字符串操作?
  • 删除元素还可以用del shoplist[0]
  • 有时候在试index的时候发现list里面并没有这个数字,这时可以用try来解决
  • list来删除元素:curr.next = curr.next.next
  • 有时候array search的方式可能不是从左到右
try:
    thing_index = thing_list.index(thing)
except ValueError:
    thing_index = -1
#下面两种写法等价
dp += min(dp[-i * i] for i in range(1, int(len(dp) ** 0.5 + 1))) + 1, #注意这个逗号
dp += [min(dp[-i * i] for i in range(1, int(len(dp) ** 0.5 + 1))) + 1]

如何找到一个loop的开始?

List comprehension: 就是以前说的那个错误的’‘生成器’’

元组Tuple

  • 元组是不可变的,用括号进行分隔。括号可带可不带,最好带着
  • 元组里面可以包含元组
  • 想生成只有一个元素的tuple需要a = (2,)
  • tuple可以直接赋值(x,y,z) = (1,2,3) 但是我发现list好像也可以
  • append功能只能通过重新赋值来实现。a = (1,2); a = a + (3,)

逻辑

  • xxx in list/tuple:会返回逻辑值

模块

  • 模块里面的函数用点来连接:math.ceil()天花板函数
  • 模块在编译中会产生.pyc文件,使得下一次载入包更加快速
  • 使用点来选取模块中的部分
  • 内置的 dir() 函数能够返回由对象所定义的名称列表。 如果这一对象是一个模块,则该列表会包括函数内所定义的函数、类与变量。vars有时候也能干一样的事情

17.7.3

可以在终端中输入python来创造一个交互式环境【像R语言的窗口】,输入exit()来退出
以.py结尾的文件每一行python代码的运行结果不会自动打印,需要在外面套一个print()
python可以直接输入16进制的数 以0x开头
print(’’’…’’’)可以使得输入过程变为多行,此时只要括号没扩上都可以用空格来换行『三个单引号』
布尔运算分为and or not
None表示空值
//表示取除法得数 %取余数
想分两行打印s2和s4,两种解决方案:print(s2,s4,sep=’’); print(s2,’\n’+s4)
print(str1+str2) 可以将两个字符无缝衔接

ord(‘str’)获取字符的整数表示 chr(num)把编码转换为对应的字符
字符创建方式可以用十六进制:a = ‘\u4e2d\u6587’
以unicode表示的字符可以编码为指定的bytes: ‘ABC’.encode(‘ascii’) ‘中文’.encode(‘utf-8’)
把bytes变为str,需要用decode: b’ABC’.decode(‘ascii’)
同种编码互相转的话,会报错
len(‘str’)可以求出str包含多少字符,也可以求出bytes的字节数:len(b’ABC’),也可以求出list的元素个数

当源代码中包含中文时,需要在文件开头写上两行:
#!/usr/bin/env python3 第一行告诉linux/OSX系统这是一个python可执行程序
# -- coding: utf-8 -- 第二行告诉要按UTF-8来进行编码

格式化占位符:「亲爱的xxx你好!你xx月的话费是xx,余额是xx」
‘Hi, %s, you have %d’ % (‘Michael’,1000) 如果只有一个%?,后面的括号可以省略。
常见的占位符有: %d整数 %f浮点数 %s字符串 %x十六进制整数 %%来转义%
例子:可以决定是否补0以及小数的位数

‘%2d-%02d’ % (3, 1)
’ 3-01’
‘%.2f’ % 3.1415926
‘3.14’

拆解Tuple:
x=(1,2,3,4)
a,b,c,d=x

而有序列表Tuple使用小括号,一旦初始化便不能再更改,可以从中提取元素,但不能再进行赋值删除等其他操作。
产生只有一个元素的Tuple时,要加一个逗号消除歧义。 t = (1,)

for in循环记得最后加冒号
range()可以生成一个整数序列(从0开始),然后还可以再用list()转换
break直接跳出循环,continue结束本次循环并直接开始下一轮循环

数据放入dict可以加快查找和插入的速度 d = {‘Michael’: 95, ‘Bob’: 75, ‘Tracy’: 85},
但dict需要占用大量的内存
可以直接通过key来放入新的数据 d[‘Adam’]=67
‘Thomas’ in d 来判断key「Thomas」是否存在与d
dict的key必须是不可变对象,因为这个算法是通过Key来计算位置的,这种叫哈希算法。因此list因为具有可变的性质,不能被作为dict的key。
x{‘name’:email}我们可以设置三种循环:
①for name in x:
print(x[name]) #会输出email
②for email in x.values():
print(email) #也会输出email
③for name,email in x,items():
print(name)
print(email) #会打印出来name和email

d.get(‘str’,-1) 如果’str’存在于d就返回’str’对应的值,否则返回-1
d.pop(‘str’)删除d中的str以及它对应的值

set也是一组key的集合,但不存储value。
s.add(new)添加新元素 s.remove()可以删除元素
两个集合可以做数学上的交集与并集。 s1&s2是交集 s1|s2是并集
bool(xx)可以把xx变成True/False
hex()十进制to十六进制,bin()十进制to二进制 bin(x^y)比较xy各个位数一样的写0不一样的写1
空函数: def nop(): pass 可以用作占位符,先让其他代码能运行起来。

定义函数时可以顺便加上数据类型检查: if not isinstance(x,(int,float))
raise TypeError(‘bad operand type’)
检验多个参数时可用
f=[False for x in (a,b,c) if not isinstance(x,(int,float))]
if f:
raise TypeError(‘Bad Type’) 注意:False首字母大写才表示错误的意思

import math 导入math包 允许使用sin/cos等函数
定义参数的时候可以默认参数:def power(x, n=2): 意思便是如果power(2,5)便计算2的五次方,如果power(4)便默认计算4的平方。
注意:①必选参数必须放在默认参数之前,②默认参数必须指向不变对象。
def add_end(L=[]):
L.append(‘END’)
return L 在不停的调用add_end()时,就会出问题,因为此时默认参数指向了一个可变对象

可变参数:def calc(*args): 同时 *args表示把args这个list所有的元素作为可变参数传进去。
关键字参数:def person(name, age, **kw): 可以在输入的时候填入除了必选项之外的信息,person(‘Bob’, 35, city=‘Beijing’)像这里的city就属于关键字参数
extra表示把extra这个dict所有的key-value用关键字参数传入到函数的kw参数
限制关键字参数的名字:def person(name, age, *, city, job):命名关键字参数
def person(name, age, args, city, job):后面的city与job就不需要再添加
命名关键字参数也可以有缺省值。
参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

递归时防止栈溢出的方式:使最后的return仅返回递归函数本身,不能包含表达式。这种方式又被称为尾递归。

创建一个1,3,5…99的列表:list(range(1,100,2)) 或者 list(range(100))[1::2]

面向对象编程

Object-oriented是否是面向对象编程主要看是不是具有关键字Class(如汇编和Pascal就没有,他们是面向过程process-oriented)

类Class

我们为什么需要Class?

  1. 每个object有多个属性
  2. 需要针对这些属性建立一些能完成特殊需求的函数:比如查找…

Coding style: 像self._value这样,就默认了value这个值是内部封装的一个变量,用户最好不要随意玩耍,这样通过变量名字来暗示这一点

  • def __init__(self,): Constuctor:对想操作的对象进行初始化,相当于造出来了一个object。可以把其他的函数看做设计的蓝图,而init可以看做是开始施工
  • class SchoolMember: self 在class的第一行并不出现
  • __del__或者__len__ 都有各自的触发条件,本质上跟__init__ 属于一类函数。这种函数一般都不会被直接call,有其他方式来调用

class listnode(object) #这样会直接生成new-style class 额所以老师建议也放一个object进去

class里面的__.xxx 的变量是不能被用户直接调用的

class xxx():
    def __init(self,value):
        self.value = value
        self.__value = value
s = xxx(5)
print(s.value) #会输出5
print(s.__value) #会报错

文件

  • f.open(‘file.txt’,‘w’) 打开一个本地文件 ('w’写入模式,'r’只读模式, 'a’追加模式) (还可以选择’t’文本模式,'b’二进制模式)类似的函数还有f.write, f.close, f.readline.
  • io.open(…, encoding = ‘utf-8’) 可以选择语言。
  • pickle.dump/pickle.load 进行文件的封装和拆封

异常

  • 在我们有可能遇到异常的时候,可以采取try的方法。我们将所有可能引发异常或错误的语句放在 try 代码块中,并将相应的错误或异常的处理器 (Handler)放在 except 子句或代码块中。 except 子句可以处理某种特定的错误或异常, 或者是一个在括号中列出的错误或异常。如果没有提供错误或异常的名称,它将处理所有错误与异常。

    try:

    text = input('Enter something --> ')

    except EOFError:

    print(‘Why did you do an EOF on me?’)

  • 可以通过raise语句触发一个用户自定义的Exception类

  • try…finally 可以使finally的部分100%会被运行,而不会受到前面的代码错误的影响

  • 如果用try finally 进行打开文件+关闭文件的操作 可以用with open来简洁的代替

#数学

  • itertools 中的permutations&combinations 可以求出排列组合

  • float(‘inf’)正无穷

  • for i,j in enumerate(nums) 要多用

  • map(operator.sub, sums[k:], sums)可以实现sums数列相差k个元素的取差。引入operator只是给出了个减法函数,类似的还有add,abs...
    <!--hexoPostRenderEscape:<pre><code class="hljs python">- 
    
    

为了注意range的用法

L[0:3]表示从索引0开始取,一直取到索引3前面的那个元素,还可以倒数切片,两个数字之差是几,就切出来几个元素
L[:]可以原样复制一个list L[::-1]可以把列表倒置
字符串也可以看成是一种list,每个元素就是一个字符
默认情况下,dict迭代的是key。如果要迭代value,可以用for value in d.values(),如果要同时迭代key和value,可以用for k, v in d.items()
enumerate可以把list变成索引元素对。给元素标上号

列表生成式的应用:
>>> L = [‘Hello’, ‘World’, ‘IBM’, ‘Apple’]
>>> [s.lower() for s in L]
>>> [‘hello’, ‘world’, ‘ibm’, ‘apple’]

生成器generator:将列表生成式中的[]变成() 中的每个元素只是保留了算法,没有展开计算,所以在调用或者打印的时候要用next()或者for循环
例如斐波那契数列:
def fib(max):
n, a, b = 0, 0, 1 注意这里的赋值语句
while n < max:
print(b)
a, b = b, a + b 注意这里的计算语句
n = n + 1
return ‘done’

把上式中的print改成yield就变成了一个generator 需要用for循环来输出值。
生成器在做的时候可以设置成无限循环,在输出的时候控制break来跳出即可

把list,dict,str等可迭代对象变成迭代器可以使用iter()函数

凡是对一个list里面的每个元素进行同一个操作的算法都可以用map: list(map(f,[]))
reduce 把一个二元函数作用在一个序列上,reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
from functools import reduce #用reduce之前要写这样一句话
字符转换成数字:
def char2num(s):
return {‘0’:0,‘1’:1,‘2’:2,‘3’:3,‘4’:4,‘5’:5,‘6’:6,‘7’:7,‘8’:8,‘9’:9}[s]

filter(f,L=[…]) 前面的f是是非判断函数,用来留下L中为True的那些元素
sorted()对一个列表排序,可以接受key:sorted([36, 5-4], key=abs),反向排序加上 reverse=True
函数下返回函数,节省运算时间空间。比如计算求和的时候存储的是一个求和的式子,待到需要运算结果的时候再对那个求和式子进行运算。下面是一个闭包实例:
def count():
def f(j):
def g():
return j*j
return g
fs = []
for i in range(1, 4):
fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
return fs

匿名函数lambda:reduce(lambda x, y: x * y, L)
函数有个__name__的属性,可以拿到函数的名字
装饰器:在代码运行简动态增加功能又不改变函数自身的定义。
import functools
def log(text):
def decorator(func):
@functools.wraps(func) #这一行目的是使得函数名称不改变
def wrapper(*args, **kw):
print(’%s %s():’ % (text, func.name))
return func(*args, **kw)
return wrapper
return decorator

偏函数functools.partial的作用是把一个函数的某些参数固定住(修改了默认值)。int2 = functools.partial(int, base=2)

安装第三方库:pip3 install Pillow 在terminal里面

x^y表示的是异或 相同输出0不同输出1
zip(*map/list)可以将这个矩阵转置(如果长度不同取最短)—输出的时候格式会有一些问题

combined=[x for j in nums for x in j] 可以把nums=[[2,3],[4,5]]变为[2,3,4,5]

17.11.17

def add_numbers(x,y,z=None):
return x+y+z
预设了z=None之后,如果输入的变量只有两个,程序也可以运行。注意提供默认值的变量必须放在变量的最后
type 可以查看变量类型

连接字符和数字的时候需要在数字外面套一个str()

字符串格式处理语言:
sales_record = {‘price’: 3.24,‘person’: ‘Chris’}
sales_statement = ‘{} bought item(s) at a price of {} each’
print(sales_statement.format(sales_record[‘person’],sales_record[‘price’]))

.shape #输出矩阵大小
.reshape(n,m) #将矩阵变成nm的矩阵 resize好像也可
Numpy:
numpy.array([],[]) #建立矩阵 如果是连接的话,默认是vertical?
numpy.arange(0,30,2) 生成一个0-28的步长为2的一维矩阵
numpy.linspace(出发,终止,个数) 创建一个一维矩阵
numpy.ones/zeros/eye/diag 创建全是1、全是0、标准阵、对角阵(把一个已知n维向量变成n维矩阵)
numpy.array([1,2,3]
3)和numpy.repeat([1,2,3],3) #前者是123123123,后者是111222333
numpy.vstack/hstack 竖直(水平)连接两个矩阵
numpy.random.randint 产生随机数

x.dot(y) 做x,y的点乘
z.T 做transpose
z.dtype 当前type
z.astype(‘f’) 变type为f
常用函数.sum/max/min/mean/std/argmax(输出最大值的index)
.copy 复制出来,要不然的话对复制出来的进行修改,也会改变原数据
想要同时对两个东西进行迭代 可以用zip()
索引-1表示最后一个 :-1表示除去最后一个 ::-1 将数据反向排列

# 二叉树

  • 四种遍历方式:层序:一行一行。先序:根左右。中序:左根右。后序:左右根
  • 后序遍历最后一个节点是根节点

可以在self树结构里面挂更多的信息,方便做某些题目

# 概念&哲学&错误

  • 在定义函数 时给定的名称称作“形参”(Parameters),在调用函数时你所提供给函数的值称作“实参”(Arguments)。
  • 警告:一般来说,你应该尽量避免使用 fromimport 语句,而去使用 import语句。这是为了避免在你的程序中出现名称冲突,同时也为了使程序更加易读。
  • EOFerror:end of file

对于for i in range这种循环操作,如果循环指标i无意义的话可以使用:

<span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>) <span class="hljs-comment">#用下划线来代替指标i</span></code></pre>:hexoPostRenderEscape-->

[Python命名艺术](https://www.python.org/dev/peps/pep-0008/#descriptive-naming-styles)

[nltk.download失败](https://stackoverflow.com/questions/41691327/ssl-sslerror-ssl-certificate-verify-failed-certificate-verify-failed-ssl-c#41692664)

[Error:Cannot start process, the working directory '' does not exist](<https://blog.csdn.net/u011012422/article/details/84201075>)

默认的re匹配完之后就会继续从下一个地方找,不会寻找overlap的匹配。[stackoverflow](<https://stackoverflow.com/questions/5616822/python-regex-find-all-overlapping-matches>) 里面两种解法都挺好的,第一种更妙,寻找Pattern前面的字符然后定位。





# IPython Notebook

[解决只有最后一行结果的问题](https://stackoverflow.com/questions/36786722/how-to-display-full-output-in-jupyter-not-only-last-result) :

<!--hexoPostRenderEscape:<pre><code class="hljs python"><span class="hljs-keyword">from</span> IPython.core.interactiveshell <span class="hljs-keyword">import</span> InteractiveShell
InteractiveShell.ast_node_interactivity = <span class="hljs-string">&quot;all&quot;</span></code></pre>:hexoPostRenderEscape-->









# 包包

## numpy

### 基础知识

argsort 相当于r里面的order

np.floor/ceil 地板/天花板函数

`np.delete(arr, obj, axis=None)` Return a new array with sub-arrays along an axis deleted.

 <!--hexoPostRenderEscape:<pre><code class="hljs python">data * <span class="hljs-number">10</span> <span class="hljs-comment">#每个数字都乘10</span>
data + data <span class="hljs-comment">#对应位置相加,相乘也是类似</span>
data.shape <span class="hljs-comment">#返回维数(行,列) 几乘几(每一维是多少)</span>
data.dtype <span class="hljs-comment">#返回里面数据的类型</span>
data[k,:], data[k] <span class="hljs-comment">#取出第k+1行</span>
data[:,k] <span class="hljs-comment">#取出第k+1列</span>
data[<span class="hljs-number">5</span>:] <span class="hljs-comment">#取出第五个以及之后的</span>
arr2d[<span class="hljs-number">0</span>][<span class="hljs-number">2</span>], arr2d[<span class="hljs-number">0</span>, <span class="hljs-number">2</span>] <span class="hljs-comment">#这两种写法都可以</span>
data.ndim <span class="hljs-comment"># 打印出来有几维,比如说一个4*5的二维数组,会打印出来2</span>
data.reshape(m,n) <span class="hljs-comment"># 变换维数,-1 表示缺省值,系统可以帮我们计算这里填什么</span>
arr.T <span class="hljs-comment">#转置</span>
arr.mean(), np.mean(arr) <span class="hljs-comment"># 可以求mean</span>
arr.sum(axis = <span class="hljs-number">0</span>) <span class="hljs-comment"># 求和 0是按列求和,1是按行求和</span>
arr.cumsum() <span class="hljs-comment"># 累积求和</span>
arr.sort(<span class="hljs-number">1</span>) <span class="hljs-comment">#排序 1指的是按行排序</span></code></pre>:hexoPostRenderEscape-->

<!--hexoPostRenderEscape:<pre><code class="hljs python">np.zeros((<span class="hljs-number">3</span>, <span class="hljs-number">6</span>)) <span class="hljs-comment">#生成一个3*6的全0数据</span>
np.empty((<span class="hljs-number">2</span>, <span class="hljs-number">3</span>)) <span class="hljs-comment">#随机生成一组数据,分布未知</span>
np.arange(<span class="hljs-number">0</span>, <span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-comment"># create 1d array 左闭右开 2是步长</span>
np.array([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], dtype=np.int32) <span class="hljs-comment">#dtype规定类型,默认是float64/int64</span>
<span class="hljs-comment">#dtype其他类型:np.string_(注意有个下划线), &#x27;u4&#x27;/&#x27;u8&#x27; 分别表示uint32/uint64</span>
data.astype(np.float64) <span class="hljs-comment">#astype来改变类型,将小数变成整数的时候,直接扔掉了小数部分</span></code></pre>:hexoPostRenderEscape-->

array的slicing也只是传递了内存地址,软拷贝。

<!--hexoPostRenderEscape:<pre><code class="hljs python">arr.copy() <span class="hljs-comment">#硬拷贝,生成一份复制品</span></code></pre>:hexoPostRenderEscape-->

python支持boolean indexing,这里跟R好像啊

<!--hexoPostRenderEscape:<pre><code class="hljs python">data[name = <span class="hljs-string">&#x27;BOB&#x27;</span>] <span class="hljs-comment"># 选出namebob的那些行</span>
data[~(name = <span class="hljs-string">&#x27;BOB&#x27;</span>)] <span class="hljs-comment"># 选出name 不 是bob的那些行</span></code></pre>:hexoPostRenderEscape-->

### np系列其他函数

<!--hexoPostRenderEscape:<pre><code class="hljs python">np.dot(arr.T, arr) <span class="hljs-comment">#计算点乘/矩阵乘积</span>
x @ x.T <span class="hljs-comment">#另一种点乘的方式</span>
np.arange(<span class="hljs-number">16</span>).reshape((<span class="hljs-number">2</span>, <span class="hljs-number">2</span>, <span class="hljs-number">4</span>)).transpose((<span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">2</span>)) <span class="hljs-comment">#高维转置闪瞎我的眼,先不琢磨了,微难想</span>
arr.swapaxes(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>) <span class="hljs-comment"># 高维交换坐标轴,这里是交换第2和第三维</span>
np.sqrt(arr), np.exp(arr) <span class="hljs-comment"># Fast Element-Wise Array Functions</span>
np.maximum(x, y) <span class="hljs-comment">#### 在比较x,y两个向量的时候,居然是逐个位置进行比较的,最后返回一个向量</span>
remainder, whole_part = np.modf(arr) <span class="hljs-comment"># 将一个小数的整数部分和小数部分分别取出来</span>
np.sqrt(arr, arr) <span class="hljs-comment">#这个会将sqrt的结果传给arr,相当于 arr = np.sqrt(arr)?</span>
a,b = np.meshgrid(x,y) <span class="hljs-comment">#Matlab里面也有这个函数,生成网格矩阵,其中a的每一行是x的复制,b的每一列是y的复制,复制的次数是另一个的维数</span>
np.where(cond, xarr, yarr) <span class="hljs-comment"># 如果cond是True,返回xarr的值,如果是False,返回yarr的值</span>
np.unique(names) <span class="hljs-comment">#DISTINCT</span>
np.in1d(X,Y) <span class="hljs-comment">#逐个判断X的元素是不是在Y里面</span></code></pre>:hexoPostRenderEscape-->

Boolean 判断

<!--hexoPostRenderEscape:<pre><code class="hljs python">bools = np.array([<span class="hljs-literal">False</span>, <span class="hljs-literal">False</span>, <span class="hljs-literal">True</span>, <span class="hljs-literal">False</span>])
bools.any() <span class="hljs-comment">#True</span>
bools.all() <span class="hljs-comment">#False</span></code></pre>:hexoPostRenderEscape-->

数据存入导出

<!--hexoPostRenderEscape:<pre><code class="hljs python">np.save(<span class="hljs-string">&#x27;some_array&#x27;</span>, arr) <span class="hljs-comment">#导出为一个npy数据</span>
np.load(<span class="hljs-string">&#x27;some_array.npy&#x27;</span>) <span class="hljs-comment">#导入数据</span>
<span class="hljs-comment">###多个文件一起存</span>
np.savez(<span class="hljs-string">&#x27;array_archive.npz&#x27;</span>, a=arr, b=arr) 
arch = np.load(<span class="hljs-string">&#x27;array_archive.npz&#x27;</span>)
arch[<span class="hljs-string">&#x27;b&#x27;</span>]
<span class="hljs-comment">###</span>
np.savez_compressed(<span class="hljs-string">&#x27;arrays_compressed.npz&#x27;</span>, a=arr, b=arr) <span class="hljs-comment">#</span></code></pre>:hexoPostRenderEscape-->

Linear Algebra

<!--hexoPostRenderEscape:<pre><code class="hljs python"><span class="hljs-keyword">from</span> numpy.linalg <span class="hljs-keyword">import</span> inv, qr</code></pre>:hexoPostRenderEscape-->



np.linspace(1.5, 2.5, 9) 左闭右闭 9是数量

np.zeros/ ones/ full[填充常数] / eye [identity array]

<!--hexoPostRenderEscape:<pre><code class="hljs python">r1 = a[<span class="hljs-number">0</span>, :] <span class="hljs-comment"># rank 1 view of the first row 这个是一维的</span>
r2 = a[<span class="hljs-number">0</span>:<span class="hljs-number">1</span>, :] <span class="hljs-comment"># rank 2 view of the first row 这个是二维的</span></code></pre>:hexoPostRenderEscape-->

`a[(a > 5) & (a < 10)]` 用小括号来做boolean array

加减乘除都是point-wise

<!--hexoPostRenderEscape:<pre><code class="hljs python">print(np.dot(a, b.transpose())) <span class="hljs-comment"># 2x3, 3x2</span>
print(a.T.dot(b)) <span class="hljs-comment"># 3x2, 2x3 两种矩阵乘积的方法</span></code></pre>:hexoPostRenderEscape-->

python支持broadcasting,两个维数不同的矩阵进行加减

* Rule:https://docs.scipy.org/doc/numpy-1.15.0/user/basics.broadcasting.html
* 维数能操作:从最后一位往前看,每一位都需要满足:
  * 两个维数相等 
  * 其中一个维数是1 
  * 要是有一个维数更长,多出来的那一部分不用管

### Random

<!--hexoPostRenderEscape:<pre><code class="hljs python">np.random.normal(loc=<span class="hljs-number">0.0</span>, scale=<span class="hljs-number">1.0</span>, size=(<span class="hljs-number">4</span>, <span class="hljs-number">4</span>)) <span class="hljs-comment"># </span>
<span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> normalvariate <span class="hljs-comment">#Multivariate </span>
np.random.randint(low, high=<span class="hljs-literal">None</span>, size=<span class="hljs-literal">None</span>, dtype=<span class="hljs-string">&#x27;l&#x27;</span>)</code></pre>:hexoPostRenderEscape-->

[random.seed 与 random.state的区别](https://stackoverflow.com/questions/22994423/difference-between-np-random-seed-and-np-random-randomstate)

<!--hexoPostRenderEscape:<pre><code class="hljs python">rng = np.random.RandomState(<span class="hljs-number">1234</span>)
rng.randn(<span class="hljs-number">10</span>)</code></pre>:hexoPostRenderEscape-->

`np.random.seed(42) #产生随机种子`

`np.random.choice(np.arange(100),size=[10,3],replace=True)` 随机抽样

`np.random.shuffle` 

<!--hexoPostRenderEscape:<pre><code class="hljs python">np.random.randn(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>) <span class="hljs-comment"># 用来产生正态N(0, 1)随机数,参数只是维数,如果想改变方差均值,需要在外面自己做变换</span></code></pre>:hexoPostRenderEscape-->





## pandas

### DataFrame

- info() 返回数据基本信息和数据内容
- value_counts() 计数
- .head()/ .tail() 返回前五行和最后五行

<!--hexoPostRenderEscape:<pre><code class="hljs python">dat_tmp = dat.iloc[:,<span class="hljs-number">0</span>:<span class="hljs-number">2</span>] <span class="hljs-comment"># 选取某几列</span></code></pre>:hexoPostRenderEscape-->

<!--hexoPostRenderEscape:<pre><code class="hljs python">ans.to_csv(<span class="hljs-string">&#x27;save.csv&#x27;</span>, index = <span class="hljs-literal">False</span>) <span class="hljs-comment">#df - csv index指的是是否保存rowname</span></code></pre>:hexoPostRenderEscape-->

<!--hexoPostRenderEscape:<pre><code class="hljs python">my_dataframe.columns.values <span class="hljs-comment">#Get header</span></code></pre>:hexoPostRenderEscape-->

[条件的取出行](https://stackoverflow.com/questions/17071871/select-rows-from-a-dataframe-based-on-values-in-a-column-in-pandas)

### Series



## collection

### Counter

把一个list缩成一个字典,key就是list里面的元素,value就是元素重复的次数
- most_common(k) 可以返回k个最多的元素

**defaultdict**(list) #创立一个value是list的初始dict,可以直接如下操作

<!--hexoPostRenderEscape:<pre><code class="hljs python">counts = defaultdict(int)
<span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> sequence:
    counts[x] += <span class="hljs-number">1</span> <span class="hljs-comment">#不用去在意x是否原先在counts里面 会被intialize to 0</span></code></pre>:hexoPostRenderEscape-->




## itertools

- accumulate: 相当于numpy里面的cumsum

## operator

- sub 减法 用来配合map使用

## heapq

* nlargest/nsmallest 可以求出序列中前几个最大值/最小值

## networkx

https://networkx.github.io/documentation/networkx-1.10/index.html

## matplotlib

Mac端Pycharm不能直接画图,需要

* 用代码`print(matplotlib.get_backend())` 查看输出是否为MACOSX,如果是的话:
* 参考这个网页:[修改默认画图选项](https://stackoverflow.com/questions/47834643/how-can-i-run-matplotlib-in-pycharm-on-macos)
* 另外注意必须先写`import matplotlib`, 再写`import matplotlib.pyplot as plt`

[判断一个点是否在多边形里面](https://stackoverflow.com/questions/16625507/python-checking-if-point-is-inside-a-polygon)





## bisect

* 在比较tuple的时候会比较每个元素,而不只是tuple的第一元素。对于数字我们可以用`float('Inf')` 来控制大小,对于字符的话最小值为`''`, 最大值目前还没有想法,不过有个老哥提出了`'z'*101` 我有点好奇



## Seaborn

<!--hexoPostRenderEscape:<pre><code class="hljs python"><span class="hljs-keyword">import</span> Seaborn <span class="hljs-keyword">as</span> sns</code></pre>:hexoPostRenderEscape-->

一共有五种预设主题,通过`sns.set_style('whitegrid')` 来修改。

* darkgrid,whitegrid,dark,white,和ticks

<!--hexoPostRenderEscape:<pre><code class="hljs python">sns.distplot <span class="hljs-comment">#画出密度分布</span></code></pre>:hexoPostRenderEscape-->

## tkinter

制作交互界面

https://morvanzhou.github.io/tutorials/python-basic/tkinter/3-03-example3/

## 其他包包

**ast**: 

* [输出set到本地](https://stackoverflow.com/questions/46144452/writing-a-set-to-an-output-file-in-python)

**spacy**:

* [无法加载en包](https://github.com/hamelsmu/Seq2Seq_Tutorial/issues/1)





# 操作技巧

- cmd+/ 快速批量注释。还可以在想注释内容的前后加上三个单引号
- help('function') 帮助手册
- 一行如果想输入多个代码语句,中间用分号连接
- *Command+Option+L* 一键使代码符合规范
- 

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!