小姐姐Python隐藏技能合集,推特2400赞,代码可直接运行ID:QbitAI)授权转载,转载请联系出处。经常发布资源的Nvidia工程师ChipHuyen发布了一组Python隐藏函数。这都是她“以前从未发现过,或者以前不敢使用的”。机器学习技能,可以直接用notebook跑。该集合称为python-is-cool。推特发布不到半天,就已经获得了2400+的点赞。小姐姐的Python隐藏技能合集,推特2400个赞,代码可以直接“跑”>那么,这个让人跑来跑去的资源到底长什么样呢?五类隐藏技能,正如开篇所言,这里的功能,要么让小姐姐费了好大的功夫,要么让她瑟瑟发抖不敢尝试。而现在,她的技能已经成功的支配了这些功能,所以,她才分了出来。目前有5个板块,专注于机器学习,后续会持续更新:1.Lambda,Map,Filter,Reducefunctionlambda关键字用于创建内联函数(InlineFunctions)。这里的square_fn和square_ld函数是一样的。1defsquare_fn(x):2returnx*x34square_ld=lambdax:x*x56foriinrange(10):7assertsquare_fn(i)==square_ld(i)lambda函数可以快速声明,所以非常适合用作回调(Callbacks)function:只是作为参数(Arguments)传递给其他函数的那种函数。对map、filter和reduce等函数特别有效。map(fn,iterable)会将fn应用于iterable的所有元素,返回一个map对象。1nums=[1/3,333/7,2323/2230,40/34,2/3]2nums_squared=[num*numfornuminnums]3print(nums_squared)45==>[0.1111111,2263.04081632,1.085147,1.384083,0.44444444]这样调用,跟用带回调函数的map调用是一样的。1nums_squared_1=map(square_fn,nums)2nums_squared_2=map(lambdax:x*x,nums)3print(list(nums_squared_1))45==>[0.1111111,2263.04081632,1.085147,1.384083,0.44444444]maperable也可以有不止一个iterable.例如,如果要计算一个简单线性函数f(x)=ax+b的均方误差(MSE),这两种方法是等价的。1a,b=3,-0.52xs=[2,3,4,5]3labels=[6.4,8.9,10.9,15.3]45#Method1:usingaloop6errors=[]7fori,xinenumerate(xs):8errors.append((a*x+b-labels[i])**2)9result1=sum(errors)**0.5/len(xs)1011#Method2:usingmap12diffs=map(lambdax,y:(a*x+b-y)**2,xs,labels)13result2=sum(diffs)**0.5/len(xs)1415print(result1,result2)1617==>0.350891721190455140.35089172119045514需要注意的是map和filter返回的是迭代器(Iterator),意思是它们的值不是存储的,而是按需生成的。调用sum(diffs)后,diffs为空。如果要将所有元素保留在差异中,请使用list(diffs)将其转换为列表。filter(fn,iterable)和map一样,只是fn返回的是布尔值,filter返回iterable中fn返回True的所有元素。1bad_preds=filter(lambdax:x>0.5,errors)2print(list(bad_preds))34==>[0.8100000000000006,0.6400000000000011]reduce(fn,iterable,initializer)用于迭代应用某个运算符。例如,如果要计算列表中所有元素的乘积:1product=12fornuminnums:3product*=num4print(product)56==>12.95564683272412上面这串代码等价于下面这串代码:1fromfunctoolsimportreduce2product=reduce(lambdax,y:x*y,nums)3print(product)45==>12.955646832724122。列表操作小姐姐说Python列表太酷了。2.1.拆包想把一个列表一个一个拆包成元素,就像这样:1elems=[1,2,3,4]2a,b,c,d=elems3print(a,b,c,d)45==>1234也可以这样:1elems=[1,2,3,4]2a,b,c,d=elems3print(a,b,c,d)45==>12342.2,切片(Slicing)大家可以知道,如果要反转列表,请使用[::-1]。1elems=列表(范围(10))2print(elems)34==>[0,1,2,3,4,5,6,7,8,9]56print(elems[::-1])78==>[9,8,7,6,5,4,3,2,1,0]和[x:y:z]这种语法意味着从索引x到索引y,每个z元素占一个。如果z为负,则反转。如果未指定x,则默认为遍历列表的方向遇到的第一个元素。如果未指定y,则默认为列表的最后一个元素。因此,如果我们想从列表中每两个取一个,那就是[::2]。1evens=elems[::2]2print(evens)34reversed_evens=elems[-2::-2]5print(reversed_evens)67==>[0,2,4,6,8]8[8,6,4,2,0]你也可以使用这个方法删除列表中的所有偶数,只留下奇数:1delelems[::2]2print(elems)34==>[1,3,5,7,9]2.3.插入(Insertion)用另一个值替换列表中一个元素的值。1elems=list(range(10))2elems[1]=103print(elems)45==>[0,10,2,3,4,5,6,7,8,9]如果要放某个index将一个元素替换为多个元素,例如将1替换为20、30、40:1elems=list(range(10))2elems[1:2]=[20,30,40]3print(elems)45==>[0,20,30,40,2,3,4,5,6,7,8,9]如果要在索引0和索引1之间插入3个值0.2,0.3,0.5:1elems=list(范围(10))2elems[1:1]=[0.2,0.3,0.5]3print(elems)45==>[0,0.2,0.3,0.5,1,2,3,4,5,6,7,8,9]2.4。展平如果列表中的每个元素都是一个列表,您可以使用sum来展平它:1list_of_lists=[[1],[2,3],[4,5,6]]2sum(list_of_lists,[])34==>[1,2,3,4,5,6]如果是嵌套列表(NestedList),可以通过递归的方法压平。这是使用lambda函数的另一种美妙方式:您可以在创建函数的同一行中使用此函数。1nested_lists=[[1,2],[[3,4],[5,6],[[7,8],[9,10],[[11,[12,13]]]]]2flatten=lambdax:[yforlinxforyinflatten(l)]iftype(x)islistelse[x]3flatten(nested_lists)45#Thislineofcodeisfrom6#https://github.com/sahands/python-by-example/blob/master/python-by-example。rst#flattening-lists2.5,listvsgenerator如果你想知道列表和生成器之间的区别,看一个例子:createn-gramsfromatokenlist。一种方法是使用滑动窗口创建:1tokens=['i','want','to','go','to','school']23defngrams(tokens,n):4length=len(tokens)5grams=[]6foriinrange(length-n+1):7grams.append(tokens[i:i+n])8returngrams910print(ngrams(tokens,3))1112==>[['i','want','to'],13['want','to','go'],14['to','go','to'],15['go','to','school']]上面这个例子中,需要同时存储所有的n-gram。如果文本中有m个标记,则内存要求为O(nm)。如果m的值太大,存储可能会成为问题。因此,没有必要使用一个列表来存储所有的n-gram。生成器可用于在接收到指令时生成下一个n-gram,这称为延迟评估(LazyEvaluation)。只要让ngrams函数返回一个带有yield关键字的生成器,内存需求就变成了O(n)。1defngrams(tokens,n):2length=len(tokens)3foriinrange(length-n+1):4yieldtokens[i:i+n]56ngrams_generator=ngrams(tokens,3)7print(ngrams_generator)89==>1011forngraminatorngrams_generator:12print(ngram)1314==>['i','want','to']15['want','to','go']16['to','go','to']17['go','to','school']另一种生成n-gram的方法是使用切片创建列表:[0,1,...,-n],[1,2,...,-n+1],…,[n-1,n,…,-1],并将它们压缩在一起。1defngrams(tokens,n):2length=len(tokens)3slices=(tokens[i:length-n+i+1]foriinrange(n))4returnzip(*slices)56ngrams_generator=ngrams(tokens,3)7print(ngrams_generator)89==>#zipobjectsaregenerators1011forngramingrams_generator:12print(ngram)1314==>('i','want','to')15('want','to','go')16('to','go','to')17('go','to','school')请注意,(tokens[…]foriinrange(n))用于创建切片,而不是[tokens[…]对于范围内的我(n)]。[]返回一个列表,()返回一个生成器。3.类,和魔法方法在Python中,魔法方法(MagicMethods)的前缀是双下划线。其中,最著名的也许是_init_。1classNode:2"""Astructtodenotethenodeofabinarytree.3Itcontainsavalueandpointerstoleftandrightchildren.4"""5def__init__(self,value,left=None,right=None):6self.value=value7self.left=left8self.right=right但是,如果要输出(打印)一个节点(Node),这不是很容易。1root=Node(5)2print(root)#<__main__.Nodeobjectat0x1069c4518>理想情况下应该输出它的值,如果有子节点,也输出子节点的值。因此,要使用魔法方法_repr_,它必须返回一个可输出的对象,例如字符串。1classNode:2"""Astructtodenotethenodeofabinarytree.3Itcontainsavalueandpointerstoleftandrightchildren.4"""5def__init__(self,value,left=None,right=None):6self.value=value7self.left=left8self.right=right910def__repr__(self):11strings=[f'value:{self.value}']12strings.append(f'left:{self.left.value}'ifself.leftelse'left:None')13strings.append(f'right:{self.right.value}'ifself.rightelse'right:None')14return','.join(strings)1516left=Node(4)17root=Node(5,left)18print(root)#value:5,left:4,right:Noneif要比较两个节点(各种值),请使用_eq_重载==运算符,使用_lt_重载<运算符,使用_ge_重载>=运算符。1classNode:2"""Astructtodenotethenodeofabinarytree.3Itcontainsavalueandpointerstoleftandrightchildren.4"""5def__init__(self,value,left=None,right=None):6self.value=value7self.left=left8self.right=right910def__eq__(self,other):11returnself。value==other.value1213def__lt__(self,other):14returnsself.value=other.value181920left=Node(4)21root=Node(5,left)22print(left==root)#False23print(left=root)#False更多魔术方法请前往:https://www.tutorialsteacher.com/python/magic-methods-in-python或使用官方文档,就是有点难读:https://docs.python.org/3/reference/datamodel.html#special-method-names在这里,还要重点安利几个神奇的方法:一个is_len_:用于重载len()函数。第二个是_str_:用于重载str()函数。第三个是_iter_:如果你想让对象成为一个迭代器,就用这个。有了它,也可以在对象上调用next()函数。对于像节点这样的类,我们已经知道它支持的所有属性:value、left、right,那么我们可以用_slots_来表示这些值。这有助于提高性能并节省内存。1classNode:2"""Astructtodenotethenodeofabinarytree.3Itcontainsavalueandpointerstoleftandrightchildren.4"""5__slots__=('value','left','right')6def__init__(self,value,left=None,right=None):7self.value=value8self。left=left9self.right=right要全面了解_slots_的优缺点,可以看看AaronHall的精彩回答:https://stackoverflow.com/a/28059785/50295954,localnamespace,objectattributelocals()函数,返回的是一个字典(Dictionary),其中包含定义在局部命名空间(LocalNamespace)中的变量。l1classModel1:2def__init__(self,hidden_??size=100,num_layers=3,learning_rate=3e-4):3print(locals())4self.hidden_??size=hidden_??size5self.num_layers=num_layers6self.learning_rate=learning_rate78model1=Model1()910==>{'learning_rate':0.0003,'num_layers':3,'hidden_??size':100,'self':<__main__.Model1objectat0x1069b1470>}一个对象的所有属性都存储在_dict_中。1print(model1.__dict__)23==>{'hidden_??size':100,'num_layers':3,'learning_rate':0.0003}注意当参数列表(ListofArguments)很大时,手动设置每个参数值赋值去房产会很累。为简单起见,您可以直接将整个参数列表分配给_dict_。1classModel2:2def__init__(self,hidden_??size=100,num_layers=3,learning_rate=3e-4):3params=locals()4delparams['self']5self.__dict__=params67model2=Model2()8print(model2.__dict__)910==>{'learning_rate':0.0003,'num_layers':3,'hidden_??size':100}这在使用kwargs**初始化对象时特别方便(尽管kwargs**应尽可能少用):1classModel3:2def__init__(self,**kwargs):3self.__dict__=kwargs45model3=Model3(hidden_??size=100,num_layers=3,learning_rate=3e-4)6print(model3.__dict__)78==>{'hidden_??size':100,'num_layers':3,'learning_rate':0.0003}前4个部分在这里。至于第5节讲授的技巧,我就不先介绍了。可以到传送门去观察:https://github.com/chiphuyen/python-is-cool贡献资源的ChipHuyen女士现在是Nvidia的高级深度学习工程师。但在2015年进入斯坦福大学学习之前,她还是一个没有接触过深度学习的作家,她已经出版了两本关于旅程故事的书。小姐姐的Python隐藏技能合集,推特2400赞,代码可以直接运行》>△是越南小姐姐,本来想主修英语,上了计算机课后,走上了深度学习的道路Lu.毕业前在Netflix实习;毕业后在斯坦福教TensorFlow,班号CS20;一年前离开学校加入NVIDIA。正式选择了机器学习,至今依然喜欢traveling把你的心得分享给大家,Qubit也不止一次介绍过这位小姐姐出品的各种资源和见解。爬取网页、清洗数据、创建海量数据集:https://mp.weixin.qq.com/s/rOXKglzYLRqTJkyLEZqJ6A免费机器学习课程,从概率统计到全栈深度学习:https://mp.weixin.qq.com/s/Jk8YuQuP5e64Q0ak-WJUKgAI从业者应该读个博士,自己创业:https://mp.weixin.qq.com/s/MTpS6RwCTLIxwP8iDbZotQ加上今天的Python隐藏技能,(至少)第四篇下一篇:传送门想要更流畅的使用Python,赶紧把这几个方法标记出来吧。项目传送门:https://github.com/chiphuyen/python-is-cool笔记本传送门:https://github.com/chiphuyen/python-is-cool/blob/master/cool-python-tips.ipynb