Python基础
1语言基础
1.1语言语义
1.1.1缩进
Python使用缩进来组织代码,而不像C++、C……使用大括号。分号可以用来分隔同一行的语句,通常不需要空格结尾。
1.1.2注释
所有在#号后面的文本都会被python解释器忽略
1.1.3函数和对象方法
函数括号内会传递0个或者多个参数,并会返回一个值赋给变量。
result=f(x,y,z)
obj.some_method(x,y,z)
对于一个参数对象,python会有对应的方法可供调用,用点号来调用这些方法。
1.1.4变量
不做过多的介绍。
1.1.5动态引用,类型
和大多数其他语言不同的是,python的对象引用不涉及类型,变量对于对象来说只是特定命名空间下的名称,类型信息是储藏在对象自身之中的。实际上python并不是非类型化语言,如下
'5'+5
TypeError Traceback (most recent call last)
Cell In[1], line 1
----> 1 '5'+5
TypeError: can only concatenate str (not "int") to str
python的隐式转化只会发生在某些特定、明显的情况,例如整型和浮点型的转化。
1.1.6二元操作符和比较运算
普通的不做介绍,特别提一个
a is b | a和b时同一个操作对象,返回True |
---|---|
a is not b | a和b不是同一个操作对象,返回True |
a//b | a整除以b |
1.1.7可变对象和不可变对象
a_list =['foo',2,[4,5]]
a_list[2]=[3,4]
a_list
# ['foo', 2, [3, 4]]
a_tuple=(1,4,6)
a_tuple[1]=5
TypeError Traceback (most recent call last)
Cell In[7], line 2
1 a_tuple=(1,4,6)
----> 2 a_tuple[1]=5
TypeError: 'tuple' object does not support item assignment
大部分对象,例如列表、字典,Numpy数组,自定义类都是可变对象,字符串,元组则是不可变的。
1.2标量
1.2.1数值类型
在python中数值类型被分成两类,int和float。int可以储存任意大小的数字。float则表示浮点数,每个浮点都是双精度的64位数值,可以使用科学计数法表示 fval=6.78e-5
整数除法会把结果自动转化为浮点数。
1.2.2字符串
python最强大之处就在于其丰富的字符串内建操作。可以使用单引号或双引号写一个字符串字面值。含有换行的多行字符串可以通过’’’或”””来写。
c='''
This is my life
Come on
'''
c.count('\n')
#3
上文中提到,字符串是不可变的。对于很多的对象我们可以通过函数str
转化成字符串。
同样的,对于字符串,我们也可以通过一些方法转化成列表和元组。
s='python'
list(s)
#['p', 'y', 't', 'h', 'o', 'n']
s[:2]
#'py'
s[:2]叫做切片,在本章节中非常的常用。
反斜杠\是一种转义符号。用来指明特殊符号例如换行符\n。如果要在字符串中使用反斜杠\,则需要双写\。
如果文本中有大量的反斜杠,且无转义字符,则可以使用字符串前缀符号r(raw),表明这些字符是原生字符。
s=r'this\has\to\be\my\places'
两个字符串之间用+连接表示字符串的首尾相连。
字符串格式化也是非常重要的部分。可以通过字符串本身自带的format
方法来替换字符串中的格式化参数。
str1='{0:.2f} {1:s} are worth US${2:d}'
str1.format(4.5560,'Argentina Pesos',1)
#'4.56 Argentina Pesos are worth US$1'
后续章节中会详细介绍如何在数据分析时进行通用字符串处理
1.2.3布尔值
python中的布尔值写作True
和False
,布尔值可以和and
和or
合用。
True and False
# False
True or False
# True
1.2.4数据类型转换
略
1.2.5None
None是python中的NULL。表示没有显式的返回值。
1.2.6日期和时间
用自建的datetime模块
略
1.3控制流
1.3.1 if、else、elif
与其它语言无差别。
1.3.2 for循环
for循环用于遍历一个集合(列表或者元组),continue可以用来跳过本次循环,break则跳过所有for循环。
1.3.3 while循环
while循环会在条件符合的情况下一直执行代码块,直到判定为False或者break。
1.3.4 pass
就是什么都不做的意思,但是大佬经常用,用来表示缩进。
1.3.5 range
生成等差整数序列或迭代器,如下
list(range(10))
#[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
list(range(0,10,2))
#[0, 2, 4, 6, 8]
list(range(20,1,-3))
#[20, 17, 14, 11, 8, 5, 2]
1.3.6 三元表达式
value = true-expr if condition else false-expr
x=5
'Non-negative' if x>=0 else'Negative'
2 内建数据结构
python有着非常丰富的数据结构。
2.1 元组
特点:固定长度,切不可变的对象序列。
tup =4,5,6
tup
#(4, 5, 6)
nested_tup=(4,5,6),(7,8)
nested_tup
#((4, 5, 6), (7, 8))
tup=tuple('string')
tup
#('s', 't', 'r', 'i', 'n', 'g')
可以使用tuple函数将任意序列和迭代器转换成元组。tuple也可以通过[]来获取。元组本身不可以改变,但如果元组的一个对象是可变的,可以在内部进行修改
tup1=tuple(['foo',[1,4],True])
tup1[1].append(3)
tup1
#('foo', [1, 4, 3], True)
通过+可以连接元组,*可以复制元组。
2.1.1 元组拆包
我们可以把元组型的表达式赋给变量,python会对等式右边进行拆包。
tup =(4,5,6)
a,b,c=tup
b
# 5
tup =(4,5,(6,7))
a,b,(c,d)=tup
d
# 7
在其他语言中,交换可能是需要引进第三个中间变量的。但是基于python的这一特性。可以直接a,b=b,a
实现交换。
元组拆包最常使用的情况就是遍历元组或列表组成的序列。
seq =[(1,2,3),(3,4,5),(6,7,8)]
for a,b,c in seq:
print("a={0},b={1},c={2}".format(a,b,c))
#a=1,b=2,c=3
#a=3,b=4,c=5
#a=6,b=7,c=8
除此以外,还有使用*来获取任意长度的参数列表。
2.1.2 元组方法
元组由于本身的不可变性,方法比较少,最常用的是count
方法。
a=(1,2,2,4,5,6,3,5,3,6,3)
a.count(3)
# 3
2.2 列表
长度可变,内容可修改,用中括号[]
来定义或者list
类型函数来定义。
2.2.1 增加或移除元素
使用append()
可以在列表尾部添加元素。使用insert()
可以在指定位置添加元素。
使用pop()
可将指定位置的元素去除。remove()
则是移除特定元素。
通过关键字in
可以检查一个值是否在列表中。同理可以加上not
。
2.2.2连接列表
同样,列表也可以通过+
来实现列表的连接,但是在连接过程中创建了新的列表,还要复制对象。
调用列表的方法extend()
也能实现,相对于+
更加效率。
2.2.3排序
通过列表自带方法sort(),则会按从小到大排序。
2.2.4切片
[start:end:step]
2.3内建序列函数
2.3.1 enumerate
enumerate函数可以用来返回列表中的元素索引,如下。
some_list=['foo','bar','baz']
mapping={}
for i,value in enumerate(some_list):
mapping[value]=i
mapping
#{'foo': 0, 'bar': 1, 'baz': 2}
2.3.2 sorted
sorted函数返回一个任意序列中的元素新建的已派序列表。
sorted([7,1,2,5,4,8,3,6])
# [1, 2, 3, 4, 5, 6, 7, 8]
2.3.3 zip
zip将列表、元组或其他元素序列的元素配对,新建一个元组构成的列表。
seq1=['foo','bar','baz']
seq2=['one','two','three']
zipped=zip(seq1,seq2)
list(zipped)
# [('foo', 'one'), ('bar', 'two'), ('baz', 'three')]
zip常用于为同时遍历多个序列,有时候会和enumerate同时使用:
for i,(a,b) in enumerate(zip(seq1,seq2)):
print('{0}:{1},{2}'.format(i,a,b))
# 0:foo,one
# 1:bar,two
# 2:baz,three
若给定一个已配对的序列时,zip函数还可以来拆分序列。
pitchers =[('nolan','ryan'),('roger','clemens'),('schilling','curt')]
first_name,last_name=zip(*pitchers)
last_name
# ('ryan', 'clemens', 'curt')
2.3.4 reversed
reversed函数可以将序列元素倒序排列
2.4 字典
dict字典时python内建数据结构中最重要的。他还叫哈希表或者关联数组。用大括号{}时创建方式之一。用逗号将键值对分隔。
字典可以使用[]插入或者设置元素,使用in来检查,使用pop方法或者del关键字删除值,keys和values的方法来提供字典键、值的迭代器。可以使用update来将两个字典合并。
2.4.1 从序列生成字典
字典接受一个2-元组的列表作为参数。
mapping=dict(zip(range(1,5),reversed(range(1,5))))
mapping
# {1: 4, 2: 3, 3: 2, 4: 1}
2.4.2默认值
words=['apple','pineapple','ant','banana','blue']
by_letter={}
for word in words:
letter = word[0]
if letter not in by_letter:
by_letter[letter]=[word]
else:
by_letter[letter].append(word)
by_letter
# {'a': ['apple', 'ant'], 'p': ['pineapple'], 'b': ['banana', 'blue']}
字典的setdefault就是为这个目的
by_letter1={}
for word in words:
letter=word[0]
by_letter1.setdefault(letter,[]).append(word)
by_letter1
2.4.3有效的字典键类型
字典值可以为任意对象,但键必须时不可变的对象。
2.5集合
集合是一种无序且元素唯一的容器,你可以认为集合也像字典,但集合没有键只有值。集合有两种创建方式,通过set函数或者字面值与大括号语法。
集合支持数学上的集合操作,包括并集、交集、差集、联合。
a={1,2,3,4,5}
b={4,5,6,7,8}
a.union(b)
a|b
# {1, 2, 3, 4, 5, 6, 7, 8}
a.intersection(b)
a&b
# {4, 5}
a.add(x) | 加入指定元素 | |
---|---|---|
a.clear() | 清空所有元素 | |
a.remove(x) | 移除指定元素 | |
a.pop() | 移除任意元素 | |
a.union(b) | a | b |
a.update(b) | a | =b |
a.intersection(b) | a&b | |
a.intersection_update(b) | a&=b | |
a.difference(b) | a-b | |
a.difference_update(b) | a-=b | |
a.symmetric_difference(b) | a^b | |
2.6列表、集合和字典的推导式
列表推导式允许你过滤一个容器的元素,用一个简明的表达式传递给过滤器的元素,从而生成一个新的列表,基本形式为
*expr* for var in collection if *condition*
与这样的for循环是等价的
result=[]
for val in collection:
if condition:
result.append(expr)
例如:
strings=['a','b','bat','ant','small','x']
[x.lower() for x in strings if x[0]=='a']
#['a', 'ant']
集合推导式和列表推导式类似。
unique_lengths={len(x) for x in strings}
unique_lengths
# {1, 3, 5}
set(map(len,strings))
# {1, 3, 5}
2.6.1嵌套列表推导式
all_data=[['john','sam','adele','lilith','steven','juan']]
names_of_interest=[]
for names in all_data:
enough_es=[name for name in names if name.count('e')>=2]
names_of_interest.extend(enough_es)
names_of_interest
# ['adele', 'steven']
3函数
函数无论在任何语言中都是不可替代的重要组成部分。函数是用来代码组织和代码复用方式。如果需要每次重复相同或类似的代码,就值得写一个可复用的函数。
函数声明时使用def关键字,返回时使用return关键字。
可以有多条return,如果没有会自动返回None。
每个函数都可以有位置参数和关键字参数,关键字参数一定在位置参数后面。
3.1命名空间、作用域和本地函数
函数连接变量有两种方式:全局、本地。在函数内部,任意变量都是默认分配给本地命名空间的,在调用时生成,执行结束后就销毁。
在函数外部给变量赋值是可以的,但那些变量必须使用global关键字声明为全局变量
3.2返回多个值
3.3函数是对象
由于python的函数时对象,很多在其它语言中比较难的构造在python中非常容易实现。假设我正在做数据清洗,需要将一些变形应用到下列字符串列表中:
states=['alabma','georgia!-','georgia','flOrida','south Carlina#$']
import re
def clean_strings(strings):
result=[]
for value in strings:
value = value.strip()
value = re.sub('[-!#$]','',value)
value = value.title()
result.append(value)
return result
clean_strings(states)
# ['Alabma', 'Georgia', 'Georgia', 'Florida', 'South Carlina']
可以将str.title、str.strip等函数当成变量来使用。
3.4匿名(Lambda)函数
匿名函数就是一种通过单个语句生成的函数,相对于完整的函数,匿名函数有的时候会更加简洁。
def apply_to_list(some_list,f):
return [f(x) for x in some_list]
ints =[4,0,1,5,7]
apply_to_list(ints,lambda x:x*2)
# [8, 0, 2, 10, 14]
3.5柯里化
表示通过部分参数应用的方式从已有的函数中衍生出新的函数。
略
3.6生成器
有点复杂,还没研究懂😳
4文件和操作系统
数据处理中需要大量使用从硬盘中读取文件,虽然有pandas.read_rsv之类的高级工具用来读取,但最基础的仍然需要掌握。
打开文件进行读写,需要使用内建函数open和绝对、相对路径:
默认情况下文件是以只读模式‘r’打开的。我们可以像处理列表一样处理文件,并遍历每一行的内容。
使用open来创建文件对象时,在结束操作时显式的关闭文件也是非常重要的,这样会释放资源放回操作系统。另一种方式就是用with open会在with代码块结束后自动关闭。
对于可读取的文件,最常用的方法就是read、seek和tell。不方便展示。