首页 > 编程语言 >《流畅的Python第二版》读书笔记——函数作为一等对象

《流畅的Python第二版》读书笔记——函数作为一等对象

时间:2022-10-15 23:02:50浏览次数:67  
标签:__ 调用 函数 读书笔记 Python 一等 参数 def name


引言

这是《流畅的Python第二版》抢先版的读书笔记。Python版本暂时用的是python3.10。为了使开发更简单、快捷,本文使用了JupyterLab。

函数是Python的一等(first-class)对象。一等对象作为一个程序实体可以:

  • 在运行时创建
  • 分配给数据结构中的变量或元素
  • 作为函数的参数
  • 作为函数的返回值

整数、字符串和字典是Python其他的一等对象的例子。本章和第三部分的大部分内容探讨了将函数作为对象来处理的实际应用。

新内容简介

无法直接找到对应的旧版本章节,基本上以前章节内容的整合,同时加入了新内容。

将函数看成对象

下面的代码显示了Python函数是对象。这里我们创建一个函数,调用它,读取​​__doc__​​​属性,然后检查函数对象本身是​​function​​类的实例。

def factorial(n): # 这是控制台session,所以我们在运行时创建函数
"""返回 n!"""
return 1 if n < 2 else n * factorial(n - 1)
factorial(42)
1405006117752879898543142606244511569936384000000000
factorial.__doc__ # 是function对象的几个属性之一
'返回 n!'
type(factorial) # factorial是function类的一个实例
function
help(factorial) # __doc__属性用于生成对象的帮助文本
Help on function factorial in module __main__:

factorial(n)
返回 n!

下面显示一个函数对象的一等本质。我们可以将它赋值为变量​​fact​​​,然后通过该名称调用它。我们也可以传递​​factorial​​​作为​​map​​​函数的参数。调用​​map(function, iterable)​​​返回一个可迭代对象,其中,每项是将第一个参数(函数)调用到第二个参数(可迭代)的连续元素的结果,本例中为​​range(10)​​。

fact =
<function __main__.factorial(n)>
fact(5)
120
map(factorial, range(11))
<map at 0x1c67cda15b0>
list(map(factorial, range(11)))
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]

具有一等的函数,可以以函数式风格进行编程。函数式编程的特点之一是使用高阶函数,我们的下一个主题介绍。

高阶函数

一个函数如果它能以函数作为参数或能返回函数,那么它就是高阶函数。一个例子就是上面演示的​​map​​​,另一个例子是内置的函数​​sorted​​​:可选的​​key​​​参数可以让你提供一个函数来应用到要排序的每项。比如,要根据单词列表中每个单词的长度排序,将​​len​​​函数作为​​key​​传递:

fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
sorted(fruits, key=len)
['fig', 'apple', 'cherry', 'banana', 'raspberry', 'strawberry']

任何只有一个参数的函数都能作为这个​​key​​​。比如,为了创建一个押韵字典,那么能通过每个单词拼写反向排序时非常有用的。
只有它们的逆序拼写作为排序准则,所以这些浆果(berries)出现在一起。

def reverse(word):
return word[::-1]

reverse('testing')
'gnitset'
sorted(fruits, key=reverse)
['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']

在函数式编程的范式中,一些最著名的高阶函数是​​map​​​、​​filter​​​、​​reduce​​​和​​apply​​​。其中​​apply​​​已经从Python3中移除。
如果你需要带动态参数集的方式调用一个函数,你可以通过​​​fn(*args, **kwargs)​​​而不是​​apply(fn, args, kwargs)​​。

​map​​​、​​filter​​​和​​reduce​​高阶函数仍然可用,但,如下一节所示,大多数情况下都有更好的替代者。

map,filter和reduce的最新替代者

函数式语言通常会提供​​map,filter,reduce​​​等高阶函数。​​map​​​和​​filter​​​函数也是Python3内置的,但自引入了列表推导式和生成器表达式后,它们不再那么重要了。一个列表推导式或生成器表达式同时完成了​​map​​​和​​filter​​的工作,而且更加可读。

list(map(factorial, range(6))) # 构建一个阶乘 0!到5!
[1, 1, 2, 6, 24, 120]
[factorial(n) for n in range(6)] # 同样的操作,通过列表推导式实现
[1, 1, 2, 6, 24, 120]
list(map(factorial, filter(lambda n: n % 2, range(6)))) # 使用map和filter实现对奇数计算阶乘,从0到5
[1, 6, 120]
[factorial(n) for n in range(6) if n % 2] # 列表推导式的实现,可替代map和filter,并且不需要lambda
[1, 6, 120]

在Python3中,​​map​​​和​​filter​​返回生成器——一种迭代器形式——所以它们的直接替代者是生成器表达式。

​reduce​​​函数从Python 2中的内置函数降级到Python 3中的​​functools​​​模块。它最常见的用例是,总和(summation),通过自Python2.3引入的内置函数​​sum​​来实现更好。可以同时带来可读性和性能的提升。

from functools import reduce # 自Python3.0,reduce不再是内置函数
from operator import add # 引入add避免创建一个只进行两个数的加法函数
reduce(add, range(100)) # 为从0到99的整数求和
4950
sum(range(100)) # 通过sum来完成同样的任务——所以不需要引入和调用reduce和add
4950

其中内建的reducing函数是​​all​​​和​​any​​:

  • ​all(iteralbe)​​​ 返回​​True​​​如果​​iterable​​​中没有​​False​​​元素,​​all([])​​​返回​​True​​。
  • ​any(iterable​​​ 返回​​True​​​如果​​iterable​​​中任意一个元素为​​True​​​,​​any([])​​​返回​​False​​。

要使用高阶函数,有时可以方便地创建一个小的、一次性的函数。这就是为什么匿名函数(anonymous function)存在。接下来我们将介绍它们。

匿名函数

​lambda​​关键字可以通过一个Python表达式创建一个匿名函数。

然而,简单的语法限制​​lambda​​​函数体只能是纯表达式。即,函数体不能包含其他语句,比如​​while​​​、​​try​​​等。通过​​=​​​赋值语句也是一个语句(statement),所以它也不能出现在​​lambda​​​表达式中,新的赋值表达式语法——​​:=​​​——可以使用,但你使用它的话,你的​​lambda​​​表达式会非常复杂,从而可读性不好。因此应该使用​​def​​重构为常规的函数。

匿名函数的最佳使用是在高阶函数的参数列表上下文中。比如,下面是通过​​lambda​​​重写的押韵索引例子,不需要定义一个​​reverse​​函数。

fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
sorted(fruits, key=lambda word: word[::-1])
['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']

在高阶函数参数的有限上下文之外,匿名函数在Python中很少有用。语法限制往往使非三元​​lambda​​​不可读或不工作。如果一个​​lambda​​不可读,强烈推荐遵循Fredrik Lundh的重构建议:

  1. 写注释来解释一下,lambda到底在做什么
  2. 研究一下评论,想出一个能抓住评论本质的名称
  3. 使用该名称将lambda转换为def语句
  4. 删除评论

​lambda​​​语法只是语法糖:一个​​lambda​​表达式创建一个就像def语句一样的函数对象。这只是Python中几种可调用对象之一。下面的部分将回顾一下所有的可调用对象。

九种常用的可调用对象

调用操作​​()​​​可以应用到其他非函数对象。为了决定一个对象是否可调用,使用内建的​​callable()​​函数。正如Python3.9 data model文档中列出的9种可调用类型:

  • 用户定义的函数 通过​​def​​​语句或​​lambda​​表达式创建
  • 内建函数 基于C(CPython)实现的函数,像​​len​​​或​​time.strftime​
  • 内建方法 基于C实现的方法,像​​dict.get​
  • 方法 定义在类中的方法
  • 类 当调用时,一个类会运行它的​​__new__​​​方法去创建一个实例,然后通过​​__init__​​​去初始化它,最终该实例会返回给调用者。因为Python中无​​new​​操作符,所以调用一个类就像调用一个函数
  • 类实例 如果一个类定义了​​__call__​​方法,那么它的实例可被作为函数调用
  • 生成器函数 函数或方法中使用了​​yield​​关键字。当调用时,它们会返回一个生成器对象
  • 原生协程函数 函数或方法基于​​async def​​定义。当调用时,它们会返回一个协程对象
  • 异步生成器函数 函数或方法基于​​async def​​​定义并在方法体中有​​yield​​关键字。当调用时,它们返回一个异步生成器

生成器、原生协程和异步生成器函数与其他可调用对象不同,它们的返回值不是应用数据,而是需要进一步处理以生成应用程序数据或执行有用的工作的对象。生成器函数返回迭代器(iterator)。这两个都会在17章中接收。原生协程函数和异步生成器函数返回的对象只能在异步编程框架中可用,比如​​asyncio​​。这是第21章的主题。

考虑到Python中现有可调用类型的多样性,确定对象是否可调用的最安全方法是使用内建的​​callable()​​:

abs, str, 'Ni!'
(<function abs(x, /)>, str, 'Ni!')
[callable(obj) for obj in (abs, str, 'Ni!')]
[True, True, False]

用户定义的可调用类型

任意的Python对象的行为都可能和函数一样,只要实现​​__call__​​实例方法。

下面的例子实现了一个​​BingoCage​​​类。实例是由任何可迭代对象构建的,并以随机顺序存储内部​​itmes​​列表。调用它的实例会弹出其中一个item元素。

import random

class BingoCage:
def __init__(self, items):
self._items = list(items) # __init__方法接收任何可迭代对象,构建一个本地副本
random.shuffle(self._items) # 对_items进行洗牌

def pick(self): # 主要的方法
try:
return self._items.pop()
except IndexError:
raise LookupError('pick from empty BingoCage') # 如果self._item为空,则抛出异常

def __call__(self): # bingo.pick() 等同于 bingo()
return self.pick()

下面来实验一下。注意​​bingo​​​实例可像函数一样被调用,并且​​callable()​​也知道它是可调用对象:

bingo = BingoCage(range(3))
bingo.pick()
1
bingo()
0
callable(bingo)
True

实现​​__call__​​​的类是一种简单的方式去创建类函数的对象,它们可具有一些在调用之间保存的内部状态,像​​BingoCage​​​中剩下的​​items​​​一样。
另一个​​​__call__​​的用例是实现装饰器。装饰器必须是可调用的,而且如果能记住调用间的状态很方便,或将复杂的实现拆分成几个方法。

函数式途径创建具有内部状态的函数是闭包(closure),它和装饰器是第9章的主题。

从位置到仅关键字参数

Python函数的最好特性之一是及其灵活的参数处理机制。密切相关的是,当我们调用一个函数时,使用​​*​​​和​​**​​​将迭代内容和映射解包到单独的参数中。
下面通过代码来看一下该特性。

def tag(name, *content, class_=None, **attrs):
"""Generate one or more HTML tags"""
if class_ is not None:
attrs['class'] = class_

attr_pairs = (f' {attr}="{value}"' for attr, value in sorted(attrs.items()))
attr_str = ''.join(attr_pairs)

if content:
elements = (f'<{name}{attr_str}>{c}</{name}>' for c in content)
return '\n'.join(elements)
else:
return f'<{name}{attr_str} />'

​tag​​函数可以通过多种方式调用:

tag('br') # 单个位置位置产生该name对应的空tag
'<br />'
tag('p', 'hello') # 在第一个参数之后的任意数量参数由*content捕获为元组
'<p>hello</p>'
print(tag('p', 'hello', 'world'))
<p>hello</p>
<p>world</p>
tag('p', 'hello', id=33) # 在tag函数签名中无显示命名的关键字参数由**attrs捕获为字典
'<p id="33">hello</p>'
print(tag('p', 'hello', 'world', class_='sidebar')) #  class_参数只能作为关键字参数传入
<p class="sidebar">hello</p>
<p class="sidebar">world</p>
tag(content='testing', name="img") # 第一个位置参数(name)也能通过关键字的形式传入
'<img content="testing" />'
my_tag = {'name': 'img', 'title': 'Sunset Boulevard','src': 'sunset.jpg', 'class': 'framed'}
# 在字典my_tag前加**会将该字典中所有的项作为分开的参数传入,它们然后会绑定到命名参数,未匹配的会由**attrs捕获。
# 这个例子中,my_tag字典中我们可以有一个class关键字,因为它是一个字符串,并且不与类保留词发生冲突。
tag(**my_tag)
'<img class="framed" src="sunset.jpg" title="Sunset Boulevard" />'

仅关键字(Keyword-only)参数是Python3的特性。在上面的例子中,​​class_​​​参数只能通过关键字参数的形式给定——永远不会捕获未命名的位置参数。
为了在定义函数时指定仅关键字参数,将这些参数命名,且放到具有​​​*​​​前缀的参数之后。如果你不想支持可变位置参数,但仍想要仅关键字参数,那么将​​*​​单独放到签名中,像:

def f(a, *, b):
return a, b
f(1, b=2)
(1, 2)
f(1,2)
---------------------------------------------------------------------------

TypeError Traceback (most recent call last)

Cell In [38], line 1
----> 1 f(1,2)


TypeError: f() takes 1 positional argument but 2 were given

注意仅关键字参数不需要有默认值:它们可以是强制性的,就像上面的例子。

仅位置参数

自Python3.8以来,用户定义的函数签名可以指定仅位置(positional-only)参数。该特性已经存在于内建函数,比如​​divmod(a, b)​​​,它仅能通过位置参数调用。
为了定义一个需要仅位置参数,在参数列表中使用​​​/​​。

def divmod(a, b, /):
return (a // b, a % b)

所有​​/​​​左边的参数都是仅位置参数,在​​/​​​右边,可以指定其他参数。比如,考虑上面的​​tag​​​函数,如果我们想要​​name​​​参数变为仅位置,我们可以增加​​/​​​到​​name​​后面,像:

def tag(name, /, *content, class_=None, **attrs):

用于函数式编程的包

operator模块

通常在函数式编程中,使用算术操作符作为函数是很方便的。例如,假设你想要乘以一个数字序列以计算阶乘,而不使用递归。要执行求和,可以使用​​sum​​​,但是没有乘法的等价函数。你可以使用​​reduce​​,但这需要一个函数去乘序列中的两项。

from functools import reduce

def factorial(n):
return reduce(lambda a, b: a*b, range(1, n+1))

​operator​​​模块为很多操作符提供了等价的函数,所以你不需要编码琐碎的函数像:​​lambda a, b: a*b​​。我们通过它来重写上面的例子。

from functools import reduce
from operator import mul
def factorial(n):
return reduce(mul, range(1, n+1))

另一组​​lambda​​​技巧是操作符替换函数从序列中选择项或从对象中读取属性:​​itemgetter​​​和​​attrgetter​​是实现它的构建自定义函数的工厂。

下面显示了​​itemgetter​​​的常用用法:按一个字段的值对元组列表进行排序。在示例中,​​cities​​​按国家代码(字段1)排序。本质上,​​itemgetter(1)​​​创建一个函数,给定一个集合,该函数返回索引1处的项。这比做同样事的​​lambda​​​字段更容易写和读:​​fields[1]​​。

metro_data = [
('Tokyo', 'JP', 36.933, (35.689722, 139.691667)),
('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
('São Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
]

from operator import itemgetter

for city in sorted(metro_data, key=itemgetter(1)):
print(city)
('São Paulo', 'BR', 19.649, (-23.547778, -46.635833))
('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889))
('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
('Mexico City', 'MX', 20.142, (19.433333, -99.133333))
('New York-Newark', 'US', 20.104, (40.808611, -74.020386))

如果你想​​itemgetter​​​中传递多个索引,它会以元组的形式返回对应值,这在基于多​​key​​排序时很有用:

cc_name = itemgetter(1, 0)
for city in metro_data:
print(cc_name(city))
('JP', 'Tokyo')
('IN', 'Delhi NCR')
('MX', 'Mexico City')
('US', 'New York-Newark')
('BR', 'São Paulo')

因为​​itemgetter​​​使用​​[]​​​操作符,它不仅支持序列,还支持映射和任何实现​​__getitem__​​的类。

与​​itemgetter​​​类似的​​attrgetter​​​,它创建了按名称提取对象属性的函数。如果传递多个属性名称到​​attrgetter​​​中作为参数,它还将返回一个值的元组。
此外,如果如果任何参数名称包含一个​​​.​​​,​​attrgetter​​会通过嵌套对象来检索属性。这些行为在下面展示。

from collections import namedtuple
LatLon = namedtuple('LatLon', 'lat lon') #
Metropolis = namedtuple('Metropolis', 'name cc pop coord')
# 通过 Metropolis实例构建metro_areas列表,注意嵌套的元组拆包抽取(lat,lon),并使用它们为Metropolis的coord属性构建LatLon
metro_areas = [Metropolis(name, cc, pop, LatLon(lat, lon))
for name, cc, pop, (lat, lon) in metro_data]

metro_areas[0]
Metropolis(name='Tokyo', cc='JP', pop=36.933, coord=LatLon(lat=35.689722, lon=139.691667))
metro_areas[0].coord.lat
35.689722
from operator import attrgetter

name_lat = attrgetter('name', 'coord.lat') # 定义一个attrgetter来检索name和coord.lat嵌套属性

for city in sorted(metro_areas, key=attrgetter('coord.lat')): # 使用attrgetter基于latitude排序列表
print(name_lat(city)) # 用上面定义的attrgetter来限定只显示name和latitude
('São Paulo', -23.547778)
('Mexico City', 19.433333)
('Delhi NCR', 28.613889)
('Tokyo', 35.689722)
('New York-Newark', 40.808611)

下面是在​​operator​​中定义的部分函数列表:

import operator
[name for name in dir(operator) if not name.startswith('_')]
['abs',
'add',
'and_',
'attrgetter',
'concat',
'contains',
'countOf',
'delitem',
'eq',
'floordiv',
'ge',
'getitem',
'gt',
'iadd',
'iand',
'iconcat',
'ifloordiv',
'ilshift',
'imatmul',
'imod',
'imul',
'index',
'indexOf',
'inv',
'invert',
'ior',
'ipow',
'irshift',
'is_',
'is_not',
'isub',
'itemgetter',
'itruediv',
'ixor',
'le',
'length_hint',
'lshift',
'lt',
'matmul',
'methodcaller',
'mod',
'mul',
'ne',
'neg',
'not_',
'or_',
'pos',
'pow',
'rshift',
'setitem',
'sub',
'truediv',
'truth',
'xor']

以​​i​​​为前缀和另一个运算符的构成的名称——如​​iadd​​​、​​iand​​​等_对应于原地赋值运算符——如​​+=​​​、​​&=​​等。

下面我们介绍​​methodcaller​​​,它有点类似​​attrgetter​​​和​​itemgetter​​​,可以动态地创建一个函数。创建的函数基于​​name​​调用给定对象中的方法。

from operator import methodcaller
s = 'The time has come'
upcase = methodcaller('upper')
upcase(s) # s.upper()
'THE TIME HAS COME'
hyphenate = methodcaller('replace', ' ', '-')
hyphenate(s)
'The-time-has-come'

用functools.partial冻结参数

​functools​​​模块提供了几个高阶函数。我们已经了解了​​reduce​​​。另一个是​​partial​​:给定一个可调用对象,它生成一个绑定参数预定值到原来可调用对象的新的可调用对象。这对于将接受一个或多个参数的函数调整到需要具有较少参数的回调的API很有用。

from operator import mul
from functools import partial
triple = partial(mul, 3) # 从mul创建新的triple函数,并将第一个位置参数绑定到3
triple(7) # 测试
21
list(map(triple, range(1, 10))) # 在map中使用triple,在该例子中不能使用mul
[3, 6, 9, 12, 15, 18, 21, 24, 27]

一个更有用的例子涉及到Unicode。如果你使用来自多种语言的文本,你可能需要应用unicode。在比较或存储它之前,对任何字符串应用​​ unicode.normalize('NFC', s)​​​。如果你经常这样做,那么要有一个​​nfc​​函数就很方便了,如示例所示。

import unicodedata, functools
nfc = functools.partial(unicodedata.normalize, 'NFC') # 把NFC绑定到normalize第一个参数

s1 = 'café'
s2 = 'cafe\u0301'
s1,
('café', 'café')
s1 ==
False
nfc(s1) == nfc(s2)
True

​partial​​以可调用对象作为第一个参数,接着是要绑定的任意数量的位置和关键字参数。

下面显示使用​​partial​​​在之前的​​tag​​函数上,来固定一个位置参数和一个关键字参数。

from functools import partial
picture = partial(tag, 'img', class_='pic-frame') # 通过固定第一个位置参数为`img`,和`class_`关键字参数为`pic-frame`来创建picture函数
picture(src='wumpus.jpeg') # 正如期望般的运行
'<img class="pic-frame" src="wumpus.jpeg" />'
picture # partial() 返回一个 functools.partial 对象
functools.partial(<function tag at 0x000001C67D6D69D0>, 'img', class_='pic-frame')
picture.func # functools.partial有访问原始函数和固定参数的属性
<function __main__.tag(name, *content, class_=None, **attrs)>
picture.args
('img',)
picture.keywords
{'class_': 'pic-frame'}

​functools.partialmethod​​​做的事情类似​​partial​​,但被设计成应用于方法。

参数总结

上文介绍了很多种参数类型,在结束之前,这里做一个总结。参考 https://docs.python.org/3/glossary.html#term-parameter

有五种类型的参数:

  • 位置或关键词(positional-or-keyword): 指定一个可以作为 位置参数 传入也可以作为 关键字参数 传入的实参。这是默认的形参类型,例如下面的​​foo​​​ 和​​bar​​:
def func(foo, bar=None): ...
  • 仅位置(positional-only): 指定一个只能通过位置传入的参数。 仅限位置形参可通过在函数定义的形参列表中为它们之后包含一个​​/​​​ 字符来定义,例如下面的​​posonly1​​​ 和​​posonly2​​:
def func(posonly1, posonly2, /, positional_or_keyword): ...
  • 仅关键字(keyword-only): 指定一个只能通过关键字传入的参数。仅关键字形参可通过在函数定义的形参列表中包含单个可变位置形参或者在多个可变位置形参之前放一个​​*​​​来定义,例如下面的​​kw_only1​​​ 和​​kw_only2​​:
def func(arg, *, kw_only1, kw_only2): ...
  • 可变位置(var-positional): 指定可以提供由一个任意数量的位置参数构成的序列(附加在其他形参已接受的位置参数之后)。这种形参可通过在形参名称前加​​*​​​来定义,例如下面的​​args​​:
def func(*args, **kwargs): ...
  • 可变关键字(var-keyword): 指定可以提供任意数量的关键字参数(附加在其他形参已接受的关键字参数之后)。这种形参可通过在形参名称前加​​**​​​ 来定义,例如上面的​​kwargs​​。


标签:__,调用,函数,读书笔记,Python,一等,参数,def,name
From: https://blog.51cto.com/greyfoss/5759375

相关文章

  • 实战 | 用Python和MediaPipe搭建一个嗜睡检测系统 (详细步骤 + 源码)
    导读本文将使用Python和MediaPipe搭建一个嗜睡检测系统(包含详细步骤+源码)。背景介绍   疲劳驾驶的危害不堪设想,据了解,21%的交通事故都因此而生,尤其是高速路上,大多......
  • 实战 | 用Python和OpenCV搭建一个老人跌倒智能监测系统 (步骤 + 源码)
    导读     本文将使用Python、OpenCV和MediaPipe搭建一个老人跌倒智能监测系统。背景介绍   老人监测系统是一种智能检测系统,可以检测老人是否躺在床上或是否跌倒......
  • python 模块导入
    1.模块导入模块在使用前需要先导入,导入语法如下:[from模块名]import[模块|类|变量|函数|*][as别名]常用的组合形式如:import模块名from模块名import......
  • python精灵模块示例代码
    精灵模块是一个基于pygame的游戏模块,可以让我们使用python时轻松实现动画效果和游戏,下面给出一些例子:背景化身弹球.rar:https://url18.ctfile.com/f/7715018-694756249-4ee......
  • Python程序员常犯的编码错误(一)
    1.引言在常见的编程语言中,通常有多种方法来实现同一个解决方案。如下:在本文中,我将向大家介绍五个Python程序员在不知不觉中陷入编写非优雅、复杂的Pythone代码的陷阱的具......
  • python学习——爬取数据到excel
    python的学习直接使用网页爬虫,将内容爬取到excel,也是为之后的大数据学习做铺垫。下面的代码是我爬取的豆瓣电影Top250的电影基本信息,当然,也可以爬取到数据库中#-*-cod......
  • (数据科学学习手札144)使用管道操作符高效书写Python代码
    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes1简介大家好我是费老师,一些比较熟悉pandas的读者朋友应该经常会使用que......
  • python 笔记
    变量:直接弄,不用搞类型,关于字符串有一个转义/的运用.注释:#(单行)''''''多行python没有{},用行对齐来表示函数:def+函数名(参数): 加回车下面就开始......
  • Python-excel转置,行转列,列转行
    代码importpandasaspddf=pd.read_excel('temp.xlsx',index=False)#读取需要转置的文件df=df.T#转置#df.to_excel('abc.xlsx',header=False)#另存为x......
  • python 中OS操作
    #获取系统名称In[235]:os.nameOut[235]:'nt'#win系统的名称nt#获取当前文件的绝对路径In[236]:os.getcwd()Out[236]:'D:\\djangoPro\\sample\\1''''绝对路径:从具......