diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..c38a894 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [taizilongxu]# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..485dee6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea diff --git a/Readme.md b/Readme.md index b3b5a90..7f2b2f4 100644 --- a/Readme.md +++ b/Readme.md @@ -119,10 +119,6 @@ - - - - # Python语言特性 ## 1 Python的函数参数传递 @@ -134,7 +130,7 @@ a = 1 def fun(a): a = 2 fun(a) -print a # 1 +print(a) # 1 ``` ```python @@ -142,7 +138,7 @@ a = [] def fun(a): a.append(1) fun(a) -print a # [1] +print(a) # [1] ``` 所有的变量都可以理解是内存中一个对象的“引用”,或者,也可以看似c中void*的感觉。 @@ -152,12 +148,12 @@ print a # [1] ```python a = 1 def fun(a): - print "func_in",id(a) # func_in 41322472 + print("func_in",id(a)) # func_in 41322472 a = 2 - print "re-point",id(a), id(2) # re-point 41322448 41322448 -print "func_out",id(a), id(1) # func_out 41322472 41322472 + print("re-point",id(a), id(2)) # re-point 41322448 41322448 +print("func_out",id(a), id(1)) # func_out 41322472 41322472 fun(a) -print a # 1 +print(a) # 1 ``` 注:具体的值在不同电脑上运行时可能不同。 @@ -169,11 +165,11 @@ print a # 1 ```python a = [] def fun(a): - print "func_in",id(a) # func_in 53629256 + print ("func_in",id(a)) # func_in 53629256 a.append(1) -print "func_out",id(a) # func_out 53629256 +print("func_out",id(a)) # func_out 53629256 fun(a) -print a # [1] +print(a) # [1] ``` 这里记住的是类型是属于对象的,而不是变量。而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings, tuples, 和numbers是不可更改的对象,而 list, dict, set 等则是可以修改的对象。(这就是这个问题的重点) @@ -192,19 +188,19 @@ Python其实有3个方法,即静态方法(staticmethod),类方法(classmethod) ```python def foo(x): - print "executing foo(%s)"%(x) + print("executing foo(%s)"%(x)) class A(object): def foo(self,x): - print "executing foo(%s,%s)"%(self,x) + print("executing foo(%s,%s)"%(self,x)) @classmethod def class_foo(cls,x): - print "executing class_foo(%s,%s)"%(cls,x) + print("executing class_foo(%s,%s)"%(cls,x)) @staticmethod def static_foo(x): - print "executing static_foo(%s)"%x + print("executing static_foo(%s)"%x) a=A() @@ -240,12 +236,12 @@ class Test(object): Test.num_of_instance += 1 if __name__ == '__main__': - print Test.num_of_instance # 0 + print(Test.num_of_instance) # 0 t1 = Test('jack') - print Test.num_of_instance # 1 + print(Test.num_of_instance) # 1 t2 = Test('lucy') - print t1.name , t1.num_of_instance # jack 2 - print t2.name , t2.num_of_instance # lucy 2 + print(t1.name , t1.num_of_instance) # jack 2 + print(t2.name , t2.num_of_instance) # lucy 2 ``` > 补充的例子 @@ -257,9 +253,9 @@ class Person: p1=Person() p2=Person() p1.name="bbb" -print p1.name # bbb -print p2.name # aaa -print Person.name # aaa +print(p1.name) # bbb +print(p2.name) # aaa +print(Person.name) # aaa ``` 这里`p1.name="bbb"`是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,`p1.name`一开始是指向的类变量`name="aaa"`,但是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量,self.name不再引用Person的类变量name了. @@ -273,12 +269,14 @@ class Person: p1=Person() p2=Person() p1.name.append(1) -print p1.name # [1] -print p2.name # [1] -print Person.name # [1] +print(p1.name) # [1] +print(p2.name) # [1] +print(Person.name) # [1] ``` -参考:http://stackoverflow.com/questions/6470428/catch-multiple-exceptions-in-one-line-except-block +当类变量值为可变对象(列表、字典等)时,共享类变量可能会造成意外的结果。 + +为了避免变量混淆,推荐使用 self 来定义实例变量,使用类名或 cls 来定义类变量。对于可变对象的类变量,可以在类定义时使用深复制来避免共享。 ## 5 Python自省 @@ -290,18 +288,16 @@ print Person.name # [1] a = [1,2,3] b = {'a':1,'b':2,'c':3} c = True -print type(a),type(b),type(c) # -print isinstance(a,list) # True +print(type(a),type(b),type(c)) # +print(isinstance(a,list)) # True ``` - - ## 6 字典推导式 可能你见过列表推导时,却没有见过字典推导式,在2.7中才加入的: ```python -d = {key: value for (key, value) in iterable} +d = {key: value for (key, value) in iterable.items()} ``` ## 7 Python中单下划线和双下划线 @@ -313,13 +309,13 @@ d = {key: value for (key, value) in iterable} ... self._semiprivate = ", world!" ... >>> mc = MyClass() ->>> print mc.__superprivate +>>> print(mc.__superprivate) Traceback (most recent call last): File "", line 1, in AttributeError: myClass instance has no attribute '__superprivate' ->>> print mc._semiprivate +>>> print(mc._semiprivate) , world! ->>> print mc.__dict__ +>>> print(mc.__dict__) {'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'} ``` @@ -356,6 +352,16 @@ AttributeError: myClass instance has no attribute '__superprivate' http://stackoverflow.com/questions/5082452/python-string-formatting-vs-format + + +Python f-string 是**执行字符串格式化的最新Python 语法**。 自Python 3.6 起可用。 Python f 字符串提供了一种更快,更易读,更简明且不易出错的在Python 中格式化字符串的方式。f 字符串的前缀为f,并使用{}括号评估值。 在冒号后指定用于类型,填充或对齐的格式说明符。 + +```python +name = "小明" +age = 20 +print(f"{name}的年龄是{age}岁!") #小明的年龄是20岁! +``` + ## 9 迭代器和生成器 这个是stackoverflow里python排名第一的问题,值得一看: http://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python @@ -374,7 +380,9 @@ http://stackoverflow.com/questions/5082452/python-string-formatting-vs-format >>> g at 0x0000028F8B774200> ``` -通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含百万元素的列表,不仅是占用很大的内存空间,如:我们只需要访问前面的几个元素,后面大部分元素所占的空间都是浪费的。因此,没有必要创建完整的列表(节省大量内存空间)。在Python中,我们可以采用生成器:边循环,边计算的机制—>generator +通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含百万元素的列表,不仅是占用很大的内存空间,如:我们只需要访问前面的几个元素,后面大部分元素所占的空间都是浪费的。因此,没有必要创建完整的列表(节省大量内存空间)。 + +在Python中,我们可以采用生成器:边循环,边计算的机制—>generator ## 10 `*args` and `**kwargs` @@ -385,7 +393,7 @@ http://stackoverflow.com/questions/5082452/python-string-formatting-vs-format ```python >>> def print_everything(*args): for count, thing in enumerate(args): -... print '{0}. {1}'.format(count, thing) +... print(f'{count}. {thing}' ... >>> print_everything('apple', 'banana', 'cabbage') 0. apple @@ -398,7 +406,7 @@ http://stackoverflow.com/questions/5082452/python-string-formatting-vs-format ```python >>> def table_things(**kwargs): ... for name, value in kwargs.items(): -... print '{0} = {1}'.format(name, value) +... print('{name} = {value}') ... >>> table_things(apple = 'fruit', cabbage = 'vegetable') cabbage = vegetable @@ -417,7 +425,7 @@ def table_things(titlestring, **kwargs) ```python >>> def print_three_things(a, b, c): -... print 'a = {0}, b = {1}, c = {2}'.format(a,b,c) +... print('a = {a}, b = {b}, c = {c}') ... >>> mylist = ['aardvark', 'baboon', 'cat'] >>> print_three_things(*mylist) @@ -449,7 +457,7 @@ http://stackoverflow.com/questions/3394835/args-and-kwargs 又比如list.extend()方法中,我们并不关心它的参数是不是list,只要它是可迭代的,所以它的参数可以是list/tuple/dict/字符串/生成器等. -鸭子类型在动态语言中经常使用,非常灵活,使得python不想java那样专门去弄一大堆的设计模式。 +鸭子类型在动态语言中经常使用,非常灵活,使得python不像java那样专门去弄一大堆的设计模式。 ## 13 Python中重载 @@ -476,20 +484,20 @@ http://stackoverflow.com/questions/3394835/args-and-kwargs 这篇文章很好的介绍了新式类的特性: http://www.cnblogs.com/btchenguang/archive/2012/09/17/2689146.html -新式类很早在2.2就出现了,所以旧式类完全是兼容的问题,Python3里的类全部都是新式类.这里有一个MRO问题可以了解下(新式类是广度优先,旧式类是深度优先),里讲的也很多. +新式类很早在2.2就出现了,所以旧式类完全是兼容的问题,Python3里的类全部都是新式类.这里有一个MRO问题可以了解下(新式类继承是根据C3算法,旧式类是深度优先),里讲的也很多. > 一个旧式类的深度优先的例子 ```python class A(): def foo1(self): - print "A" + print("A") class B(A): def foo2(self): pass class C(A): def foo1(self): - print "C" + print("C") class D(B, C): pass @@ -631,10 +639,42 @@ Python里最常见的yield就是协程的思想!可以查看第九个问题. 闭包就像个空心球一样,你知道外面和里面,但你不知道中间是什么样. +```python +def count_time_wrapper(func): + def improved_func(): + start_time = time.time() + func() + end_time = time.time() + print(f"it takes {end_time - start_time}s to find all the olds") + + return improved_func + # 闭包本质上是一个函数 + # 闭包函数的传入参数和返回值都是函数 + # 闭包函数的返回值函数是对传入函数进行增强的函数 +``` + ## 21 lambda函数 其实就是一个匿名函数,为什么叫lambda?因为和后面的函数式编程有关. +```python +f = lambda x: x * x +print(f(4)) #16 + +g = lambda x, y: x + y +print(g(1, 2)) #3 + + +def que(a, b, c): + return lambda x: a * x * x + b * x + c + +# 第一种写法 +f = que(-1, 1, 2) #-18 +print(f(5)) +# 第二种写法 +print(que(-1, 1, 2)(5)) #-18 +``` + 推荐: [知乎](http://www.zhihu.com/question/20125256) @@ -651,7 +691,7 @@ filter 函数的功能相当于过滤器。调用一个布尔函数`bool_func` ```python >>>a = [1,2,3,4,5,6,7] >>>b = filter(lambda x: x > 5, a) ->>>print b +>>>print(b) >>>[6,7] ``` @@ -685,10 +725,10 @@ d = copy.deepcopy(a) #对象拷贝,深拷贝 a.append(5) #修改对象a a[4].append('c') #修改对象a中的['a', 'b']数组对象 -print 'a = ', a -print 'b = ', b -print 'c = ', c -print 'd = ', d +print('a = ', a) +print('b = ', b) +print('c = ', c) +print('d = ', d) 输出结果: a = [1, 2, 3, 4, ['a', 'b', 'c'], 5] @@ -697,6 +737,10 @@ c = [1, 2, 3, 4, ['a', 'b', 'c']] d = [1, 2, 3, 4, ['a', 'b']] ``` +**浅拷贝: 创建新对象,其内容是原对象的引用。** + +**深拷贝:和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。深拷贝出来的对象是一个全新的对象,不再与原来的对象有任何关联。** + ## 24 Python垃圾回收机制 Python GC主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率。 @@ -878,18 +922,20 @@ Bulid过程可以分解为4个步骤:预处理(Prepressing), 编译(Compilation) 1. 页是信息的物理单位,分页是为了实现非连续分配,以便解决内存碎片问题,或者说分页是由于系统管理的需要.段是信息的逻辑单位,它含有一组意义相对完整的信息,分段的目的是为了更好地实现共享,满足用户的需要. 2. 页的大小固定,由系统确定,将逻辑地址划分为页号和页内地址是由机器硬件实现的.而段的长度却不固定,决定于用户所编写的程序,通常由编译程序在对源程序进行编译时根据信息的性质来划分. -3. 分页的作业地址空间是一维的.分段的地址空间是二维的. +3. 分页的作业地址空间是一维的、分段的地址空间是二维的。 ## 8 页面置换算法 -1. 最佳置换算法OPT:不可能实现 -2. 先进先出FIFO -3. 最近最久未使用算法LRU:最近一段时间里最久没有使用过的页面予以置换. -4. clock算法 +页面置换:在地址映射过程中,若所要访问的页面不在内存中,则产生了‘缺页中断(page fault)’。此时操作系统必须在内存中选择一个页面将其移出内存,为即将调入的页面让出空间。 +1. 最佳置换算法 OPT (optional replacement):被替换的页面为在未来最长时间内不会被访问的页面,可保证最低的缺页率,但不可能实现,主要用于评估算法。 +2. 先进先出 FIFO:最易实现,但会频繁换页,性能差。 +3. 最近最久未使用算法 LRU (Least Recently Used):最近一段时间里最久没有使用过的页面予以置换。 +4. 时钟替换算法 (Clock):依照使用位替换页面。 ## 9 边沿触发和水平触发 -边缘触发是指每当状态变化时发生一个 io 事件,条件触发是只要满足条件就发生一个 io 事件 +1. 边沿触发 (Edge Trigger):自上次状态改变后有新的 I/O 事件就会触发通知,需要尽可能多的执行 I/O 操作。 +2. 水平触发 (Level Trigger):准备就绪时(可非阻塞地执行 I/O 系统调用)触发通知,可在任意时刻重复检测 I/O 状态。 # 数据库 @@ -900,10 +946,7 @@ Bulid过程可以分解为4个步骤:预处理(Prepressing), 编译(Compilation) ## 2 数据库索引 -推荐: http://tech.meituan.com/mysql-index.html - -[MySQL索引背后的数据结构及算法原理](http://blog.codinglabs.org/articles/theory-of-mysql-index.html) - +推荐: https://zhuanlan.zhihu.com/p/113917726 聚集索引,非聚集索引,B-Tree,B+Tree,最左前缀原理 ## 3 Redis原理 @@ -1315,7 +1358,7 @@ list(set(l)) ```python l1 = ['b','c','d','b','c','a','a'] l2 = {}.fromkeys(l1).keys() -print l2 +print(l2) ``` 用字典并保持顺序 @@ -1324,7 +1367,7 @@ print l2 l1 = ['b','c','d','b','c','a','a'] l2 = list(set(l1)) l2.sort(key=l1.index) -print l2 +print(l2) ``` 列表推导式 @@ -1430,7 +1473,7 @@ def recursion_merge_sort2(l1, l2): 再把旧列表加到新列表后面 -```pyhton +```python def loop_merge_sort(l1, l2): tmp = [] while len(l1) > 0 and len(l2) > 0: @@ -1569,21 +1612,21 @@ def node(l1, l2): ```python #coding:utf-8 -def binary_search(list,item): +def binary_search(list, item): low = 0 - high = len(list)-1 - while low<=high: - mid = (low+high)/2 + high = len(list) - 1 + while low <= high: + mid = (high - low) / 2 + low # 避免(high + low) / 2溢出 guess = list[mid] - if guess>item: - high = mid-1 - elif guess item: + high = mid - 1 + elif guess < item: + low = mid + 1 else: return mid return None mylist = [1,3,5,7,9] -print binary_search(mylist,3) +print(binary_search(mylist, 3)) ``` @@ -1603,7 +1646,7 @@ def quicksort(list): finallylist = quicksort(lessbeforemidpivot)+[midpivot]+quicksort(biggerafterpivot) return finallylist -print quicksort([2,4,6,7,1,2,5]) +print(quicksort([2,4,6,7,1,2,5])) ``` @@ -1632,7 +1675,7 @@ def coinChange(values,valuesCounts,money,coinsUsed): if (temp < minCoins): minCoins = temp coinsUsed[cents] = minCoins - print ('面值:{0}的最少硬币使用数为:{1}'.format(cents, coinsUsed[cents])) + print('面值:{0}的最少硬币使用数为:{1}'.format(cents, coinsUsed[cents])) ``` @@ -1678,7 +1721,7 @@ def lookup(root): def deep(root): if not root: return - print root.data + print(root.data) deep(root.left) deep(root.right) @@ -1705,7 +1748,7 @@ class Node(object): #中序遍历:遍历左子树,访问当前节点,遍历右子树 def mid_travelsal(root): - if root.left is None: + if root.left is not None: mid_travelsal(root.left) #访问当前节点 print(root.value) @@ -1728,7 +1771,7 @@ def post_trvelsal(root): post_trvelsal(root.left) if root.right is not None: post_trvelsal(root.right) - print (root.value) + print(root.value) ``` @@ -1747,9 +1790,9 @@ def maxDepth(root): def isSameTree(p, q): if p == None and q == None: return True - elif p and q : + elif p and q: return p.val == q.val and isSameTree(p.left,q.left) and isSameTree(p.right,q.right) - else : + else: return False ``` @@ -1772,7 +1815,7 @@ def deep(root): return deep(root.left) deep(root.right) - print root.data + print(root.data) ``` ## 21 单链表逆置 @@ -1798,7 +1841,7 @@ def rev(link): root = rev(link) while root: - print root.data + print(root.data) root = root.next ``` @@ -1895,4 +1938,3 @@ class Anagram: > 可参考:[动态规划(DP)的整理-Python描述](http://blog.csdn.net/mrlevo520/article/details/75676160) -