python日常工作+基础再复习

20201226更新:df.join连接后,保证左连接的df的index不被排序

caller.join(other.set_index('uid'), on='uid')

#DataFrame的join连接时,caller的关键列  默认为index(可以使用参数on指定别的列为关键列);
#但是other的关键列永远都是index,所有使用别的列为关键列时,常常使用set_index()

df2 = pd.read_clipboard()

df = df1.join(df2.set_index('uid'),on='uid')
df = df.fillna('0')
df['share_uv'] = df['share_uv'].astype('int')
df.to_excel('D:/2020.xlsx')

20200917更新

【pivot_table解决pivot的重复问题】
The pivot_table method comes to solve this problem.
It works like pivot, but it aggregates the values from rows with duplicate entries for the specified columns.
【stack后变高,unstack后变宽】

python日常工作+基础再复习_第1张图片
stack后变高,unstack后变宽

Reshaping in Pandas - Pivot, Pivot-Table, Stack, and Unstack explained with Pictures

python基础再复习

【Python内建了map()、reduce()、filter()、sorted()函数】

  • map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
  • reduce()把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
  • filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list。
  • sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序,例如按绝对值大小排序。key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果进行排序。
from functools import reduce

【可迭代对象(可以直接作用于for循环的对象):Iterable】VS【迭代器(被next()函数调用并不断返回下一个值的对象,表示一个惰性计算的序列):Iterator】生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。把list、dict、str等Iterable变成Iterator可以使用iter()函数:

所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。
而使用list是永远不可能存储全体自然数的。

【生成器:一边循环一边计算的机制,称为生成器:generator(列表生成式的[]改成(),就创建了一个generator;generator保存的是算法)】通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

定义generator的另一种方法。如果一个函数定义中包含yield关键字,
那么这个函数就不再是一个普通函数,而是一个generator
而变成generator的函数,在每次调用next()的时候执行,
遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。


【在一个列表生成式中,for前面的if ... else是表达式,而for后面的if是过滤条件,不能带else】

把if写在for前面必须加else,否则报错
 [x if x % 2 == 0 else -x for x in range(1, 11)]

跟在for后面的if是一个筛选条件,不能带else
[x for x in range(1,11) if x%2==0]

【列表生成式:使用两层循环,可以生成全排列】

 [m + n for m in 'ABC' for n in 'XYZ']

【如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断】Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身

>>> from collections import Iterable
>>> isinstance('abc', Iterable) 
# str是否可迭代

【必选参数、默认参数(必须指向不变对象)、可变参数(numbers,表示传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple)、命名关键字参数(定义命名的关键字参数在没有可变参数的情况下不要忘了写分隔符,否则定义的将是位置参数)和关键字参数(传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict)】
默认参数有个最大的坑(定义默认参数要牢记一点):默认参数必须指向不变对象!Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。

【默认参数(必须指向不变对象)】
def add_end(L=None):
    if L is None:
        L = []
    L.append('END')
    return L


def add_end(L=[]):
    L.append('END')
    return L
【可变参数(*numbers,表示传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple)】
如果已经有一个list或者tuple,要调用一个可变参数怎么办?可以这样做:

>>> nums = [1, 2, 3]
>>> calc(nums[0], nums[1], nums[2])
14
这种写法当然是可行的,问题是太繁琐,所以Python允许你在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去:

>>> nums = [1, 2, 3]
>>> calc(*nums)
14
*nums表示把nums这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。
【关键字参数(传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict)】
传入任意个数的关键字参数:

>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

【函数可以返回多个值吗?答案是肯定的;函数可以同时返回多个值,但其实就是一个tuple】
函数定义:如果有必要,可以先对参数的数据类型做检查;
Python函数返回的仍然是单一值。返回值是一个tuple!但是,在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便。

【import】如果你已经把abs()的函数定义保存为abstest.py文件了,那么,可以在该文件的当前目录下启动Python解释器,用from abstest import my_abs来导入my_abs()函数,注意abstest是文件名(不含.py扩展名)

┌────────────────────────────────────────────────────────┐
│Command Prompt - python                           - □ x │
├────────────────────────────────────────────────────────┤
│>>> from abstest import my_abs                          │
│>>> my_abs(-9)                                          │
│9                                                       │
│>>> _                                                   │
│                          

【list和dict的优缺点】

  • 和list比较,dict(dict是空间换时间:查找快,但内存大)有以下几个特点:
    查找和插入的速度极快,不会随着key的增加而变慢;
    需要占用大量的内存,内存浪费多。
    dict的key必须是不可变(如字符串、整数,而list是可变的,就不能作为key)对象。这个通过key计算位置的算法称为哈希算法(Hash)。要保证hash的正确性,作为key的对象就不能变。
  • 而list(list是时间换空间:查找慢,但内存小)相反:
    查找和插入的时间随着元素的增加而增加;
    占用空间小,浪费内存很少。

【循环】
break语句可以在循环过程中直接退出循环,而continue语句可以提前结束本轮循环,并直接开始下一轮循环。break和continue这两个语句通常都必须配合if语句使用
【不变对象】
为什么要设计str、None这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。

【tuple的 指向不变 VS 内容不变】tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向'a',就不能改成指向'b',指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!

>>> t = ('a', 'b', ['A', 'B'])
>>> t[2][0] = 'X'
>>> t[2][1] = 'Y'
>>> t
('a', 'b', ['X', 'Y'])
【表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。】

【格式化输出%s和%d】

如果你不太确定应该用什么,%s永远起作用,它会把任何数据类型转换为字符串:
>>> 'Age: %s. Gender: %s' % (25, True)
'Age: 25. Gender: True'

【当Python解释器读取源代码时,为了让它按UTF-8编码读取,我们通常在文件开头写上这两行】

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
第一行注释是为了告诉Linux/OS X系统,这是一个Python可执行程序,Windows系统会忽略这个注释;
第二行注释是为了告诉Python解释器,按照UTF-8编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。
【!】申明了UTF-8编码并不意味着你的.py文件就是UTF-8编码的,必须并且要确保文本编辑器正在使用UTF-8 without BOM编码

【互联网编码:ASCII、Unicode和UTF-8的关系】
把字符串(一种数据类型)编码为数字,才能为计算机处理;
8个比特(bit)作为一个字节(byte);
美国人发明计算机,美国人制定ASCII编码;
中国制定GB2312编码(中文至少需要两个字节),各国有各国的标准;
Unicode把所有语言都统一到一套编码里(ASCII编码和Unicode编码的区别:ASCII编码是1个字节,而Unicode编码通常是2个字节,故Unicode编码比ASCII编码需要多一倍的存储空间)【在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。】;
本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码(如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间)【UTF-8编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。】。

python日常工作+基础再复习_第2张图片
搞清楚了ASCII、Unicode和UTF-8的关系,我们就可以总结一下现在计算机系统通用的字符编码工作方式

你可能感兴趣的