AI_Learn

AI-learning

Q&A

2022年8月18日22:45:19

Q:在ipython中运行run试的时候,无法成功会出现如下错误提示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fWBF7YLk-1661576171052)(C:\Users\光明斗士\AppData\Roaming\Typora\typora-user-images\image-20220818224816164.png)]

A

  • 由于python2.x和python3.x在print语句上有语法差别;

  • pyhon2.x : print"hello,world"无需加上括号;

  • python3.x :print(“hello,world”)需加括号;

    所以文件的写入应该为
    %%writefile helllo_world.py

    print(“hello world”)

Q 返回上一层文件的命令。

A %cd(空格)…(空格)。

Q 使用matplotlib画的图这么找?还是说显示不出来图像,目前不知道原因。

A

Q Python中有一种叫做列表推导式(List comprehension)的用法,还是咩很看懂。

Q notebook打不开?

anaconda环境切换

一、先创建一个新的虚拟环境

conda create --name my_test python=3.7#创建一个名称为my_test

二、激活虚拟环境

activate my_test

三、查看环境

conda env list

note

-位于括号中的指针可以直接通过回车直接跳转到最后的位置。

-如果需要在文字中插入括号可以直接选中插入括号。

-需要跳过间冒号可以在按一次冒号。

-对于单引号'',在输入完单引号的内容之后可以再摁单引号即可将光标对到单引号之外,对于所有的对称符号都可以这样处理,包括[],"",{}

数字

整型integers

python2.7中整型运算只能返回整型,包括除法。

12/5
2#python2.7
2.4#python3.7

幂指数

2**5
32

取余

32%5
2

浮点数folating point numbers

整数除浮点数得到浮点数。

12/5.0
2.4

复数complex numbers

在python中用j来表示虚部。

a = 1+2j

实部

a.real

虚部

a.imag

共轭(实部相同,虚部相反)

a.conjugate()

布尔型 boolean data type

布尔型数据取特殊的二值变量,为truefalse

字符串

字符串采用单引号’'或者双引号""均可以生成字符串,而且相同,任何地方使用到字符串均需要带引号

s = "hello world"
s = 'hello world'

字符串的简单操作

加法

s = ’hello‘ + 'world'
print (s)
'hello world'

字符串和数字相乘

"echo"*3
'echoechoecho'

字符串长度

len(s)

字符串方法

面向对象的语言,其中一个不可少的元素就是方法。

方法调用方式如下:

对象.方法()

分割

s.split(sep)将按照给定的sep为分隔符对s进行分割,返回一个列表

其中sep可以是空格(sep不写默认值)也可是制表符\t换行符\n

line = "1 2 3 4 5"
numbers = line.split()
print numbers
['1','2','3','4','5'] #返回值是列表list

按照sep给定的内容分割 需要加个单引号''

line = "1,2,3,4,5"
numbers = line.split(',')
print numbers
['1','2','3','4','5'] #返回值是列表list

连接

和分割相反,s.join(str_sequence)的作用就是将s中的每两个字符串元素用str_sequence连接起来,返回连接后的字符串。

numbers = "12345"
s = ','
s.join(numbers)
'1,2,3,4,5'

替换

s.replace(part1,part2)将字符串s中的part1替换成part2,并返回替换后的字符串。

s = "hello world"
s.replace('world','python')
'hellow pthyon'

大小写转换

s.upper()返回一个将s中的字母全部大写的新字符串,不改变原始值。

"hello world".upper()
'HELLO WORLD'

s.lower()返回一个将s中的字母全部小写的新字符串,不改变原始值。

"HELLO WORLD".lower()
'hello world'

去空格

s.strip()返回一个去除s两端多余空格的新字符,不改变原始值。

s = "  hello world  "
s.strip()
'hello world'

s.lstrip()返回一个去除s开头多余空格的新字符,不改变原始值。

s = "  hello world  "
s.lstrip()
'hello world  '

s.rstrip()返回一个去除s开头多余空格的新字符,不改变原始值。

s = "  hello world  "
s.rstrip()
'  hello world'

多行字符串

Python采用一堆”“”或者‘‘‘来生成多行字符串。

a = '''hello world,
what a nice day!!'''
print(a)
hello world,
what a nice day!!

强制转换成字符串

str(ob)强制将ob转化成字符串。

repr(ob)也是强制将ob转化成字符串。

str(1.1 + 2.2)
'3.3'
repr(1.1 + 2.2)
'3.3000000000000003'

索引和分片

索引

对于一个有序序列,我们可以通过索引的方式访问对应位置的数值。Python采用[]对有序序列索引。

并且Python中的索引是从0开始的,所以[0]对应序列的第1个元素。

(可以这么理解,索引指针这在初始位置0处,第1个元素

[0]就表示移动0个距离;

[1]表示正向移动一个距离,所以[1]表示的是第2个元素;

[-1]表示负向移动一个距离,所以指向字符串最后一个)

s = "hellow world"
s[0]
'h'

[5]对应的是第四个元素。

s[5]
'l'

并且Python还支持负向索引,从后向前开始计数,索引[-2]表示倒数第2个元素,和正向的需要-1运算不相同

s[-2]
'l'

超出索引值会报错:

s[11]
IndexError: string index out of range
分片?

分片表示从序列中提取出需要的子序列,具体方法为:

var[lower:upper:step]

范围包括lower,不包括upper,就是[lower,upper),step表示间距,通常不写,默认为1

s = [hello world]

其中元素为 个数为upper-lwer 并且 每个数可以为负数。

​ lower为负数可以表示从倒数第三个开始,由于省略upper,所以需要计数到end

s = [-3:]
'rld'#表示从倒数第3个开始到结尾结束 

​ uppper为负数可以表示到倒数第三个为止,由于省略lower,所以需要从start计数

s = [:-3]
'hello wor'#表示从开头到里结尾3个

当step的值为负时,省略lower意味着从结尾开始分片,省略upper意味着一直分片到开头。?

s[::-1]
'dlrow olleh'

测试从属关系

使用in来判断某个元素是否在某个序列中:

s = "hello world"
print('he' in s)
True

not in来判断某个元素是否不在某个序列中:

s = "hello world"
print('he' not in s)
False

列表list

Python中,列表(list)是一个有序可以包含不同数据类型(整型,字符串,浮点)的序列。

列表用一对 [] 生成,中间的元素用 , 隔开,其中的元素不需要是同一类型,同时列表的长度也不固定,列表长度是采用区分的。

列表输出可以直接输出列表名字或者采用print()两种方式。

l = [1,2.0,'hello']
print(l)
[1, 2.0, 'hello']

空列表可以采用[]或者list()生成:

empty_list = []
empty_list
[]
empty_list = list()
print(empty_list)
[]

列表长度

此阿勇len()来查看列表长度,列表长度取决于分割内容:

l = [1,2.0,'hello']
len(l)
3

加法

列表加法,相当于两个列表顺序相加:

a = [1,2,3]
b = [3.2,'hello']
a + b
[1, 2, 3, 3.2, 'hello']

乘法

列表和和数字相乘,基本相当于列表的重复相加:

a = [1,2,3]
a*2
[1, 2, 3, 1, 2, 3]

索引和分片

索引

列表和字符串一样可以通过索引来查看元素值:

正向索引

a = [1,2,3,4,5,6]
a[0]
1

反向索引

a[-1]
 6

分片?

a[2:-1]
[3, 4]

与字符串的不同之处是,列表值可以通过索引和分片来修改。

索引修改:

a = [1,2,3,4,5]
a[0] = 100
a
[100, 2, 3, 4, 5]

分片修改:

a[1:3] = [11,12]
a
[100, 11, 12, 4, 5]

事实上,对于连续的分片(即步长为 1 ),Python采用的是整段替换的方法,两者的元素个数并不需要相同,例如,将 [11,12] 替换为 [1,2,3,4]

a = [10,11,12,13,14]
a[1:3] = [1,2,3,4]
a
[10, 1, 2, 3, 4, 13, 14]

也可以采用这种方式删除一个连续的分片:

a = [10,1,2,11,12]
a[1:3]
a[1:3] = []
a
[1, 2]
[10, 11, 12]

对于不连续(间隔step不为1)的片段进行修改时,两者的元素数目必须一致:

a = [19,11,12,13,14]
a[::2] = [1,2,3]
a
[1, 11, 2, 13, 3]

否则会报错

a = [19,11,12,13,14]
a[::2] = []
a
ValueError: attempt to assign sequence of size 0 to extended slice of size 3

删除元素

Python提供了删除列表中元素的方法 ‘del’。

删除列表中的第一个元素:

a = [1002,'a','b','c']
del a[0]
a
['a', 'b', 'c']

删除第2到最后一个元素:

a = [1002,'a','b','c']
del a[1:]
a
[1002]

删除间隔的元素

a = ['a',1,'b',2,'c']
del a[::2]
a
[1, 2]

测试从属关系

使用in来判断某个元素是否在某个序列中:

a = [10,11,12,13,14]
print (10 in a)
True

not in来判断某个元素是否不在某个序列中:

a = [10,11,12,13,14]
print (10 not in a)
False

列表中甚至可以包含列表:

a = [10,'eleven',[12,13]]
a[2]
[12, 13]

a[2]是一个列表,可以在对它进行索引:

a[2][1]
13

列表方法

不改变列表的方法

count列表某个中元素个数

l.count(ob)返回列表元素ob出现的次数。

a = [11,12,13,12,11]
a.count(11)
2

需要查询列表中的列表出现的次数:

a = [11,12,13,12,11,[11,12,13,12,11]]
a[5].count(11)
2
index列表中某个元素的位置

l.index(ob) 返回列表中元素 ob 第一次出现的索引位置,如果 ob 不在 l 中会报错。

a.index(12)
1

改变列表的方法

append向列表添加单个元素

l.append(ob) 将元素 ob 添加到列表 l 的最后。

a = [10,11,12]
a.append(11)
print(a)
[10, 11, 12, 11]

append每次只添加一个元素,并不会因为这个元素是序列而将其展开:

a.append([11,12])
print(a)
[10, 11, 12, 11, [11, 12]]
extend向列表添加序列(列表)

l.extend(lst) 将序列 lst 的元素依次添加到列表 l 的最后,作用相当于 l += lst

a = [10,11,12,11]
a.extend([1,2])
print(a)
[10, 11, 12, 11, 1, 2]
insert插入元素

l.insert(idx, ob) 在索引 idx 处插入 ob ,之后的元素依次后移。

note:idx的计数方式不和索引相同,从第一个开始计数

a = [10,11,12,13,11]
a.insert(3,'a')
print(a)
[10, 11, 12, 'a', 13, 11]
remove移除元素

l.remove(ob) 会将列表中第一个出现的 ob 删除,如果 ob 不在 l 中会报错。

a = [10,11,12,13,11]
a.remove(11)
print(a)
[10, 12, 13, 11]
pop弹出元素

l.pop(idx) 会将索引 idx 处的元素删除,idx的数值与索引相同,均为从0计数,并返回这个元素。

a = [10,11,12,13,11]
a.pop(2)
12
sort排序

l.sort()将会按照一定的规则排序,并会改变原来的值:

a = [10,1,11,13,11,2]
a.sort()
print(a)
[1, 2, 10, 11, 11, 13]

如果想不改变原来的顺序,可以使用sorteed()函数:

a = [10,1,11,13,11,2]
b = sorted(a)
print(a)
print(b)
[10, 1, 11, 13, 11, 2]
[1, 2, 10, 11, 11, 13]
reverse列表相反

l.reverse()将会将列表的元素从后向前排列,会改变原来的值:

a = [1,2,3,4,5,6]
a.reverse()
print(a)
[6, 5, 4, 3, 2, 1]

如果不想改变原来的值,可以使用分片的方法:

a = [1,2,3,4,5,6]
b = a[::-1]
print(a)
print(b)
[1, 2, 3, 4, 5, 6]
[6, 5, 4, 3, 2, 1]

元组tuple

与列表相似,元组tuple也是一个有序序列,但是元组是不可变的,采用()表示:

t = (10,11,12,13,14)
t
(10, 11, 12, 13, 14)

元组可以索引:

t(0)
10

可以切片:

t[1:3]
(11, 12)

但是元组是不可变的。

单个元素的元组生成

由于元组采用(),所以,采用以下形式定义单个元组:

a = (10,)
print(a)
type(a)
(10,)
<type 'tuple'>

而非:

a = (10)
print (type(a))
<type 'int'>

将列表转换成元组:

a = [10,11,12,13,14]
tuple(a)
(10, 11, 12, 13, 14)

元组方法

由于元组是不可变的,所以只能有一些不可变的方法,例如计算元素个数 count 和元素位置 index ,用法与列表一样。

a = [10,11,12,13,14]
a.count(10)
1
a = [10,11,12,13,14]
a.index(12)
2

速度部分:元组只是生成速度快一点,遍历和索引速度向差不多。

字典dict

字典 dictionary ,在一些编程语言中也称为 hashmap ,是一种由键值对组成的数据结构。

可以把key想象成字典里面的单词,把value想象成单词对应对的定义,所以,一个词可以对应一个或者多个定义。

字典简单操作

字典生成

在Python中采用{key:value}生成dictionary:

d = {'dog':5,'cat':4}
d
type(d)
{'dog': 5, 'cat': 4}
dict

生成一个空字典:

a = {}
a
{}

或者采用定义:

a = dict()
a
{}

len字典大小

查询一个字典的大小,字典的大小表示一组键值的大小:

d = {'dog':5,'cat':4}
len(d)
2

查看字典对应键值

d["dog"]
5

修改键值

d["dog"] = 2
d
{'dog': 2, 'cat': 4}

插入键值

可以直接在一个字典之后继续输入键值:

d["pigs"] = 7
d
{'dog': 2, 'cat': 4, 'pigs': 7}

note

-字典是没有顺序的,在我们Print一个字典,他并一定会按照键值的先后顺序显示,因为建本身不一定有序。

-键必须是不可变的类型,整型和字符串是字典中最常用的,值可以是任意类型的。

字典的方法

get返回值

get用来索引一个字典的键值,当字典中的键不存在时,便会报错,在报错的时候,get便可以来处理,返回给定的报错:

d.get(key,default = None)

返回字典dkey对应的值,如果不存在,返回defaultdefault可以省略,省略的时候就返回None,也就是啥都没有,打印出来为None,但是设定默认值之后,就会有参数返回。

d = {'dog':5,'cat':4}
print(d.get("monkey"))
d.get("monkey","undefined")
None
undefined

pop删除元素

pop用来弹出字典某个键对应的值,同时可以指定键不存在是的返回值。

d.pop(key,default = None)

删除并返回字典中key对应的值,如果没有这个值,返回defaultdefault省略时,会报错,需要设定默认返回值。

d = {'dog':5,'cat':4}
d.pop("cat")
d.pop("monkey","undefined")

del删除也是可以的:

del d["cat"]
d
{'dog': 5}

update更新字典

可以通过索引的方法来插入修改单个键值对,但是对于多个键值对操作的话,这种方式还是比较麻烦的,我们可以采用update的方法:

d.update(newd)

newdx需要修改的一个新字典中的内容更新到原字典d中。

d = {"born":2000,"age":21}
print(d)

修改2000为20005,同时插入"sex"的值为"M"

d_modific = {"born":2005,"sex":'m'}
d.update(d_modific)
print(d)
{'born': 2005, 'age': 21, 'sex': 'm'}

in查询字典中是否存在该键

in可以用来查询字典中是否存在某个特殊的键,返回值为true或者false

d = {'dog':5,'cat':4}

in可以用来查询字典中是否存在某个特殊的键

'monkey' in d
False

所有的键

d = {'dog': 2, 'cat': 4, 'pigs': 7}
d.keys()
['cats', 'dogs', 'pigs']

所有的值

d ={'dog': 2, 'cat': 4, 'pigs': 7}
d.values()
[4, 2, 7]

所有的键值对

d ={'dog': 2, 'cat': 4, 'pigs': 7}
d.items()
[('cats', 4), ('dogs', 2), ('pigs', 7)]

集合set

之前的元组,序列,字符串都是有序序列,每个位置和元素都一一对应,但是集合set是一种无序的序列,和数学上的概念相同。

当集合中出现相同元素的时候,会保留一个元素,并且存入的元素不会改变。

生成集合

Python中采用{}来生成集合(需要注意字典也是采用{}生成)集合中不含有相同元素,并且不会改变。

s = {2,3,4,2}
s

空集合生成:

a = set()
type(s)
set

而非:

s = {}
type(s)
dict

集合操作

两个集合的交,包含两个集合的所有共有元素的集合。

可以用方法 a.intersection(b) 或者操作 a & b 实现。

a = {1,2,3,4}
b = {3,4,5,6}
a.intersection(b)
b.intersection(a)
{3, 4}
{3, 4}
a & b
b & a
{3, 4}
{3, 4}

两个集合的并,也就是两个集合所有元素的集合。

可以用方法 a.union(b) 或者操作 a | b 实现。

a = {1,2,3,4}
b = {3,4,5,6}
a.union(b)
b.union(a)
{1, 2, 3, 4, 5, 6}
{1, 2, 3, 4, 5, 6}
a | b
b | a
{1, 2, 3, 4, 5, 6}
{1, 2, 3, 4, 5, 6}

ab 的差集,返回只在 a 不在 b 的元素组成的集合。

可以用方法 a.difference(b) 或者操作 a - b 实现。

a = {1,2,3,4}
b = {3,4,5,6}
a.difference(b)
b.difference(a)
{1, 2}
{5, 6}
a - b
b - a
{1, 2}
{5, 6}

对称差

ab 的对称差集,返回在 a 或在 b 中,但是不同时在 ab 中的元素组成的集合,也就是a∪b-a∩b。

可以用方法 a.symmetric_difference(b) 或者操作 a ^ b 实现(异或操作符)。

a.symmetric_difference(b)
b.symmetric_difference(a)
{1, 2, 5, 6}
a ^ b
{1, 2, 5, 6}

包含关系

要判断 b 是不是 a 的子集,可以用 b.issubset(a) 方法,或者更简单的用操作 b <= a

a = {1, 2, 3}
b = {1, 2}
b.issubset(a)
True
b <= a
True

集合方法

add向集合中添加单个元素

跟列表的append方法类似,可以向集合中添加单个元素。

s.add(a) 

将元素a添加到集合s中,注意集合无序,所以是随机添加到集合的某个位置,并非添加到末尾。

t = {1, 2, 3}
t.add(5)
t
{1, 2, 3, 5}

如果添加的是已有的元素,集合石不会改变的。

update方法相机和添加多个元素

方法和列表里面的extend差不多,可以一次向集合添加多个元素。

s.uodate(seq)

seq中的元素添加到sz中。

t.update({5,6,7})
t
{1, 2, 3, 5, 6, 7}

remove移除单个元素

s.remove(ob) 

从集合s中移除元素ob,如果不存在会报错。

t.remove(1)
t
{2, 3, 5, 6, 7}
t.remove(10)
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-31-3bc25c5e1ff4> in <module>()
----> 1  t.remove(10)

KeyError: 10

pop方法弹出元素

pop方法随机弹出一个元素,并不能指定删除元素,如果集合没有元素,那就会报错。

t.pop()
{3, 5, 6, 7}
s = set()
# 报错
s.pop()
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-34-9f9e06c962e6> in <module>()
 1 s = set()
 2 # 报错
----> 3  s.pop()

KeyError: 'pop from an empty set'

discard方法

使用方法和remove相同,可以删除指定元素,而且不会返回参数,但是当集合中不存在的时候不会报错。

t = {1, 2, 3, 4, 5, 6}
t.discard(3)
{1, 2, 4, 5, 6}
t.discard(20)
t
{1, 2, 4, 5, 6}

difference_update方法

a.difference_update(b) 

就相当于a-b

不可变集合

对应于元组(tuple)(参数不可改变)与列表(list)(参数可以改变)的关系,对于集合(set),Python提供了一种叫做不可变集合(frozen set)的数据结构。

s = frozenset([1,2,3,'a',1])
s
frozenset({1, 2, 3, 'a'})

与集合不相同的是,不可变集合一旦创建就不能修改。

不可变集合的一个主要应用是用来作为字典的键,例如用一个字典来记录两个城市之间的距离:

flight_distance = {}
city_pair = frozenset(['Los Angeles', 'New York'])
flight_distance[city_pair] = 2498
flight_distance[frozenset(['Austin', 'Los Angeles'])] = 1233
flight_distance[frozenset(['Austin', 'New York'])] = 1515
flight_distance

数据类型的可变与不可变总结

可变数据类型不可变数据类型
list, dictionary, set, numpy array, user defined objectsinteger, float, long, complex, string, tuple, frozenset

Python的赋值机制

简单类型

x = [1, 2, 3]
y = x
x[1] = 100
print y
[1, 100, 3]

改变变量x的值,变量y的值也会随之改变,这就是和Python内部的赋值机制有关。

对于赋值的变量,可以理解为将变量y定义成了一个指针,将它指向x,在内存空间中,致同一块物理内存,是同一个事物,可以采用is判断是不是指向同一事物:

x is y
True

但是对于相同的值,Python并不会对他赋予相同的内存指针。

容器类型

现在来看另一段代码:

x = [500, 501, 502]
y = x
y[1] = 600
y = [700, 800]
复制ErrorOK!
  • x = [500, 501, 502]

Python为3个PyInt分配内存 pos1pos2pos3 (不可变),然后为列表分配一段内存 pos4 ,它包含3个位置,分别指向这3个内存,最后再让变量 x 指向这个列表。

简单来说,就是创建三个储存简单值的内存,在创造一个列表,储存三个简单值的内存,然后让x指向这个列表。

内存命名空间
pos1 : PyInt(500) (不可变)
pos2 : PyInt(501) (不可变)
pos3 : PyInt(502) (不可变)
pos4 : PyList(pos1, pos2, pos3) (可变)x : pos4
  • y = x

并没有创建新的对象,只需要将 y 指向 pos4 即可。

内存命名空间
pos1 : PyInt(500) (不可变)
pos2 : PyInt(501) (不可变)
pos3 : PyInt(502) (不可变)
pos4 : PyList(pos1, pos2, pos3) (可变)x : pos4
y : pos4
  • y[1] = 600

原来 y[1] 这个位置指向的是 pos2 ,由于不能修改 pos2 的值,所以首先为 600 分配新内存 pos5

再把 y[1] 指向的位置修改为 pos5 。此时,由于 pos2 位置的对象已经没有用了,Python会自动调用垃圾处理机制将它回收

内存命名空间
pos1 : PyInt(500) (不可变)
pos2 : 垃圾回收
pos3 : PyInt(502) (不可变)
pos4 : PyList(pos1, pos5, pos3) (可变)
pos5 : PyInt(600) (不可变)x : pos4
y : pos4
  • y = [700, 800]

首先创建这个列表,然后将变量 y 指向它。

内存命名空间
pos1 : PyInt(500) (不可变)
pos3 : PyInt(502) (不可变)
pos4 : PyList(pos1, pos5, pos3) (可变)
pos5 : PyInt(600) (不可变)
pos6 : PyInt(700) (不可变)
pos7 : PyInt(800) (不可变)
pos8 : PyList(pos6, pos7) (可变)x : pos4
y : pos8

判断语句

虽然都是用 if 关键词定义判断,但与C,Java等语言不同,Python不使用 {}if 语句控制的区域包含起来。Python使用的是缩进方法。同时,也不需要用 () 将判断条件括起来。

x = -0.5
if x > 0:
    print ("Hey!")
print ("This isn't part of the block, and will always print.")

循环

while循环

while <condition>:
    <statesments> 

Python会循环执行<statesments>,直到<condition>不满足为止,注意其中condition后面有一个

i = 0
total = 0
while i < 1000000:
    total += i
    i += 1
print (total)
499999500000
plays = set(['Hamlet', 'Macbeth', 'King Lear'])
while plays:
    play = plays.pop()
    print ('Perform', play)

注意print函数的使用方法,中间采用连接:

print(var1,var2)

for循环

for <variable> in <sequence>:
    <indented block of code> 

for 循环会遍历完<sequence>中所有元素为止,注意有in和最后的variable就相当于列表里面的一个变量代表。

plays = set(['Hamlet', 'Macbeth', 'King Lear'])
for play in plays:
    print ('Perform', play)
Perform King Lear
Perform Macbeth
Perform Hamlet

函数

生成函数

函数function,通常接受输入参数,并有返回值。

def add(x, y):   #注意这里有一个冒号
    """Add two numbers"""
    a = x + y
    return a

函数通常有一下几个特征:

  • 使用 def 关键词来定义一个函数。
  • def 后面是函数的名称,括号中是函数的参数,不同的参数用 , 隔开, def foo(): 的形式是必须要有的,参数可以为空;
  • 使用缩进来划分函数的内容;
  • docstring""" 包含的字符串,用来解释函数的用途,可省略;
  • return 返回特定的值,如果省略,返回 None

使用函数

使用函数时,只需要将参数换成特定的值传给函数。

Python并没有限定参数的类型,因此可以使用不同的参数类型:

print add(2, 3)
print add('foo', 'bar')
5
foobar

设定默认值

在定义函数的时候,也可以修设置默认值:

def quad(x, a=1, b=0, c=0):
    return a*x**2 + b*x + c

在输入的时候,可以省略带有默认值的参数:

print quad(2.0)
4.0

还可以修改默认值:

print quad(2.0, b=3)
10.0

接收不定参数

如果输入的参数数目不确定,可以采用以下方法:

def add(x, *args):
	total = x
	for arg in args:
		total += arg  #将x添加到arg这个元组中
	return total

这里,*args 表示参数数目不定,可以看成一个元组,把第一个参数后面的参数当作元组中的元素。

print add(1, 2, 3, 4)
print add(1, 2)
10
3

这样定义的函数不能使用关键词传入参数,要使用关键词,可以这样:

def add(x, **kwargs):
    total = x
    for arg, value in kwargs.items():
        print "adding ", arg
        total += value
    return total

这里, **kwargs 表示参数数目不定,相当于一个字典,关键词和值对应于键值对。

print add(10, y=11, z=12, w=13)
adding  y
adding  z
adding  w
46

再看这个例子,可以接收任意数目的位置参数和键值对参数:

def foo(*args, **kwargs):
    print args, kwargs

foo(2, 3, x='bar', z=10)
(2, 3) {'x': 'bar', 'z': 10}

不过要按顺序传入参数,先传入位置参数 args ,在传入关键词参数 kwargs

返回多个值

Python中可以返回多个值:

from math import atan2
def to_polar(x,y):
	r = (x**2 + y**2) ** 0.5
	theta = atan2(y,x)
	return r, theta

r, theta = to_polar(3,4)
print(r, theta)
5.0 0.927295218002

事实上,Python将返回的两个值变成了元组:

map方法生成序列

可以通过 map 的方式利用函数来生成序列:

def sqr(x): 
    return x ** 2

a = [2,3,4]
print map(sqr, a)

[4, 9, 16]

其用法为:

map(aFun, aSeq) 

将函数 aFun 应用到序列 aSeq 上的每一个元素上,返回一个列表,不管这个序列原来是什么类型。

事实上,根据函数参数的多少,map 可以接受多组序列,将其对应的元素作为参数传入函数:

In [24]:

def add(x, y): 
    return x + y

a = (2,3,4)
b = [10,5,3]
print map(add,a,b)#将a和b的对应元素尽心add操作

[12, 8, 7]

文件读写

写入测试文件:

%%writefile test.txt
this is a test file.
hello world!
python is good!
today is a good day.
Writing test.txt

读文件

使用 open 函数或者 file (目前使用存在问题)函数来读文件,使用文件名的字符串作为输入参数:

f = open('test.txt')

读文件的方法:

——可以使用 read 方法来读入文件中的所有内容:

text = f.read()
print (text)
this is a test file.
hello world!
python is good!
today is a good day.

——也可以按照行读入内容,readlines 方法返回一个列表,每个元素代表文件中每一行的内容:

f = open('test.txt')
lines = =f.readlines()
print(lines)

使用完文件之后,需要将文件关闭

f.close()

事实上,我们可以将 f 放在一个循环中,得到它每一行的内容:

f = open('test.txt')
for line in f:
    print line
f.close()
this is a test file.

hello world!

python is good!

today is a good day.

写文件

我们使用 open 函数的写入模式来写文件:

f = open('myfile.txt', 'w')
f.write('hello world!')
f.close()

使用 w 模式时,如果文件不存在会被创建,我们可以查看是否真的写入成功:

print open('myfile.txt').read()
hello world!

如果文件已经存在, w 模式会覆盖之前写的所有内容:

another hello world!

除了写入模式,还有追加模式 a ,追加模式不会覆盖之前已经写入的内容,而是在之后继续写入:

f = open('myfile.txt', 'a')
f.write('... and more')
f.close()
print open('myfile.txt').read()
another hello world!... and more

写入结束之后一定要将文件关闭,否则可能出现内容没有完全写入文件中的情况。

f = open('myfile.txt','w+')
f.write('hello world!')
f.seek(6)
print(f.read())
f.close
world!

这里 f.seek(6) 移动到文件的第6个字符处,然后 f.read() 读出剩下的内容。



ipython magic指令

ipython解释器提供了很多以百分号%开头的magic命令,这些命令很像linux系统下的命令行命令(事实上有些是一样的)。

whos查看当前变量空间

%whos
Variable   Type    Data/Info
----------------------------
a          int     1
b          list    n=3

reset重置当前变量空间

%reset -f

之后在查看变量空间

%whos
Interactive namespace is empty.

使用pwd查看当前工作环境

%pwd
'C:\\Users\\光明斗士'

文件操作

使用 mkdir 产生新文件夹:

%mkdir demo_test

使用cd改变当前工作环境

%cd demo_test/

使用 writefile 将cell中的内容写入文件:

%%writefile hello_world.py
print "hello world"
Writing hello_world.py

使用ls查看当前文件夹的文件:

%ls
2022/08/23  16:35    <DIR>          .
2022/08/23  16:35    <DIR>          ..
2022/08/23  16:35                22 hello_world.py
               1 ���ļ�             22 �ֽ�
               2 ��Ŀ¼ 32,185,081,856 �����ֽ�

使用run来运行这段代码:

%run hello_world.py
hello world

删除文件

这个指令只能删除文件,不能删除文件夹,并且注意一定要括号!!

import os
os.remove("hello_world.py") #单双括号都可以,但一定要有括号

返回上一层文件夹:

%cd ..  #注意是%cd(空格)..(空格)

删除文件夹rmdir

注意里面有文件的时候不能删除,只有把里面的文件全部移除才能删除文件夹。

也就是说只能删除空文件!

%rmdir demo_test #demo_test必须是空文件

ipython 支持使用 <tab> 键自动补全命令。

模块和包

脚本(整体使用)

Python会将所有 .py 结尾的文件认定为Python代码文件,考虑下面的脚本 ex1.py

%%writefile ex1.py

PI = 3.1416

def sum(lst):
    tot = lst[0]
    for value in lst[1:]:
        tot = tot + value
    return tot

w = [0, 1, 2, 3]
print sum(w), PI

可以执行它:

%run ex1.py
6 3.1416

模块(可以使用内部参数)

这个脚本可以当作一个模块,可以使用import关键词加载并执行它(这里要求ex1.py在当前工作目录,也就是和这个工程的文件相同):

import ex1
6 3.1416

在导入时,Python会执行一遍模块中的所有内容。

ex1.py 中所有的变量都被载入了当前环境中,不过要使用

ex1.变量名 

的方法来查看或者修改这些变量:

print (ex1.PI)
3.1416

还可以用

ex1.函数名 

调用模块里面的函数:

print (ex1.sum([2, 3, 4]))
9

为了提高效率,Python只会载入模块一次,已经载入的模块再次载入时,Python并不会真正执行载入操作,哪怕模块的内容已经改变。

??模块和脚本的区别??

name 属性

有时候我们想将一个 .py 文件既当作脚本,又能当作模块用,这个时候可以使用 __name__ 这个属性。

只有当文件被当作脚本执行的时候, __name__的值才会是 '__main__',所以我们可以:

%%writefile ex2.py

PI = 3.1416

def sum(lst):
    """ Sum the values in a list
    """
    tot = 0
    for value in lst:
        tot = tot + value
    return tot

def add(x, y):
    " Add two values."
    a = x + y
    return a

def test():
    w = [0,1,2,3]
    assert(sum(w) == 6)
    print ('test passed.')

if __name__ == '__main__':
    test()
Writing ex2.py

运行文件(执行脚本,此时__name__的值才会是 '__main__',test会运行):

%run ex2.py
test passed.

当作模块导入, test() 不会执行:

import ex2

但是可以使用其中的变量:

ex2.PI
3.1416

使用别名,给指定函数换个名字:

import ex2 as e2
e2.PI
3.1416

其他导入方法

可以从模块中导入变量:

from ex2 import add, PI

使用 from 后,可以直接使用 addPI

也就是从ex2里面导入addPI这两个内容。

add(2, 3)
5

或者使用 * 导入所有变量:

from ex2 import *
add(3, 4.5)
7.5

这种导入方法不是很提倡,因为如果你不确定导入的都有哪些,可能覆盖一些已有的函数。

假设我们有这样的一个文件夹:

foo/

  • __init__.py
  • bar.py (defines func)
  • baz.py (defines zap)

这意味着 foo 是一个包,我们可以这样导入其中的内容:

from foo.bar import func
from foo.baz import zap

barbaz 都是 foo 文件夹下的 .py 文件。

导入包要求:

  • 文件夹 fooPython的搜索路径中
  • __init__.py 表示 foo 是一个包,它可以是个空文件。

anaconda 的jupter notebook 进入方法

直接在jupter(anaconda)中搜索

Matplotlib

关于如何导入中文字府库:

准备工作

再处理小说之前,我们需要先做一些准备工作。

因为涉及中文字符,所以我们使用 __future__ 中 Python 3 的特性,将所有的字符串转为 unicode

In [1]:

from __future__ import unicode_literals
复制ErrorOK!

再来我们解决图像里中文字符显示的问题,Matplotlib虽然支持 unicode 编码,但是直接输出中文字体会出现问题。

import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
%matplotlib inline

x = range(10)
plt.plot(x)
plt.title("中文")
plt.show()

会在jupter中出现如下图像(注意最上端并未显示中文两字,这就是中文加载不出来):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Itmw7dPt-1661576171055)(C:\Users\光明斗士\AppData\Roaming\Typora\typora-user-images\image-20220825225042888.png)]

出现上图的原因是它找不到合适的中文字体去显示中文,为此,我们可以去寻找一些支持中文的字体来进行设置。

Windows 7 及以上的系统中,字体位置为 C:/Windows/Fonts,例如:

  • 宋体:C:/Windows/Fonts/simsum.ttc

Linux 系统可以通过 fc-list 命令查看已有的字体和相应的位置,例如:

  • /usr/share/fonts/truetype/osx-font-family/Songti.ttc: Songti TC,宋體\-繁,宋体\-繁:style=Bold,粗體,粗体
  • /usr/share/fonts/truetype/osx-font-family/Devanagari Sangam MN.ttc: Devanagari Sangam MN,देवनागरी संगम एम॰एन॰:style=Bold,粗體,Fed,Fett,Puolilihava,Gras,Grassetto,ボールド,볼드체,Vet,Fet,Negrito,Жирный,बोल्ड,粗体,Negrita
  • /usr/share/fonts/truetype/osx-font-family/Iowan Old Style.ttc: Iowan Old Style,Iowan Old Style Black:style=Black Italic,Italic

也可以从网上直接下载字体

  • 比如 Yahei Consolas 的字体 YaHei.Consolas.1.11b.ttf

找到了字体的位置,我们可以使用 matplotlib.font_manager 中的FontProperties 导入字体:

这种方式就是绝对路径,这种方式需要依赖本地文件,并不好。

font_xxx = FontProperties(fname="/usr/share/fonts/truetype/osx-font-family/Songti.ttc")
font_xxx = FontProperties(fname="C://Windows//Fonts//simsum.ttc")

为了方便,我们不使用字体的绝对路径导入,而是将需要的字体放在程序对应的文件夹下:

需要注意的是,如果错误出现提示不存在文件,先检查拼写是否出错,在检查其他格式问题!

  • simsum.ttc
  • YaHei.Consolas.1.11b.ttf
from matplotlib.font_manager import FontProperties

font_simsum = FontProperties(fname="simsun.ttc")
font_yahei_consolas = FontProperties(fname="YaHei.Consolas.1.11b.ttf")

在绘图的时候进行设置:

x = range(10)
plt.plot(x)
plt.title("中文", fontproperties=font_yahei_consolas, fontsize=14)
plt.show()

title函数的使用规则就是(标题名字,字体,大小)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u8UoIcOB-1661576171056)(C:\Users\光明斗士\AppData\Roaming\Typora\typora-user-images\image-20220825232407517.png)]

在探索金庸的武侠世界中遇到的问题和解决方法

Q

Python2和Python3在处理中文的时候会发生问题,之前在看爬虫教程的时候,用到的是:

response.encoding = 'utf-8'  #改中文乱码方式1
img_name.encode('iso-8859-1').decode('gbk')  #通用处理中文乱码的方式2

但是这回,我按照网上的流程处理之后,能显示文字了,但是文字是乱码的,还是在处理文字的时候需要观察一下问题所在。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ulg063ze-1661576171057)(C:\Users\光明斗士\AppData\Roaming\Typora\typora-user-images\image-20220826001557827.png)]

Q:

UnicodeDecodeError: ‘gbk’ codec can’t decode byte 0xbf in position 2: illegal multibyte sequence

A:

在打开文本的时候encoding方式出问题,需要在打开文本的地方输入encoding = ‘utf-8’。

最终代码如下:

with open('novels/天龙八部.txt',encoding='utf-8') as f:
    # 去掉结尾的换行符
    data = [line.strip().encode('utf8').decode('utf8') for line in f.readlines()]
    #读取大段文字

for line in data[:13]:  #返回14行的列表
    if line.strip():
        print(line)

或者简单一点:

with open('novels/天龙八部.txt',encoding='utf-8') as f:
    # 去掉结尾的换行符
    data = [line.strip() for line in f.readlines()]

for line in data[:13]:
    if line.strip():
        print (line)

plot(x)
plt.title(“中文”)
plt.show()


会在jupter中出现如下图像(注意最上端并未显示中文两字,这就是中文加载不出来):

[外链图片转存中...(img-Itmw7dPt-1661576171055)]

出现上图的原因是它找不到合适的中文字体去显示中文,为此,我们可以去寻找一些支持中文的字体来进行设置。

`Windows 7` 及以上的系统中,字体位置为 `C:/Windows/Fonts`,例如:

- 宋体:`C:/Windows/Fonts/simsum.ttc`

`Linux` 系统可以通过 `fc-list` 命令查看已有的字体和相应的位置,例如:

- `/usr/share/fonts/truetype/osx-font-family/Songti.ttc: Songti TC,宋體\-繁,宋体\-繁:style=Bold,粗體,粗体`
- `/usr/share/fonts/truetype/osx-font-family/Devanagari Sangam MN.ttc: Devanagari Sangam MN,देवनागरी संगम एम॰एन॰:style=Bold,粗體,Fed,Fett,Puolilihava,Gras,Grassetto,ボールド,볼드체,Vet,Fet,Negrito,Жирный,बोल्ड,粗体,Negrita`
- `/usr/share/fonts/truetype/osx-font-family/Iowan Old Style.ttc: Iowan Old Style,Iowan Old Style Black:style=Black Italic,Italic`

也可以从网上直接下载字体

- 比如 `Yahei Consolas` 的字体 `YaHei.Consolas.1.11b.ttf`。

找到了字体的位置,我们可以使用 `matplotlib.font_manager` 中的`FontProperties` 导入字体:

这种方式就是绝对路径,这种方式需要依赖本地文件,并不好。

```py
font_xxx = FontProperties(fname="/usr/share/fonts/truetype/osx-font-family/Songti.ttc")
font_xxx = FontProperties(fname="C://Windows//Fonts//simsum.ttc")

为了方便,我们不使用字体的绝对路径导入,而是将需要的字体放在程序对应的文件夹下:

需要注意的是,如果错误出现提示不存在文件,先检查拼写是否出错,在检查其他格式问题!

  • simsum.ttc
  • YaHei.Consolas.1.11b.ttf
from matplotlib.font_manager import FontProperties

font_simsum = FontProperties(fname="simsun.ttc")
font_yahei_consolas = FontProperties(fname="YaHei.Consolas.1.11b.ttf")

在绘图的时候进行设置:

x = range(10)
plt.plot(x)
plt.title("中文", fontproperties=font_yahei_consolas, fontsize=14)
plt.show()

title函数的使用规则就是(标题名字,字体,大小)

[外链图片转存中…(img-u8UoIcOB-1661576171056)]

在探索金庸的武侠世界中遇到的问题和解决方法

Q

Python2和Python3在处理中文的时候会发生问题,之前在看爬虫教程的时候,用到的是:

response.encoding = 'utf-8'  #改中文乱码方式1
img_name.encode('iso-8859-1').decode('gbk')  #通用处理中文乱码的方式2

但是这回,我按照网上的流程处理之后,能显示文字了,但是文字是乱码的,还是在处理文字的时候需要观察一下问题所在。

[外链图片转存中…(img-ulg063ze-1661576171057)]

Q:

UnicodeDecodeError: ‘gbk’ codec can’t decode byte 0xbf in position 2: illegal multibyte sequence

A:

在打开文本的时候encoding方式出问题,需要在打开文本的地方输入encoding = ‘utf-8’。

最终代码如下:

with open('novels/天龙八部.txt',encoding='utf-8') as f:
    # 去掉结尾的换行符
    data = [line.strip().encode('utf8').decode('utf8') for line in f.readlines()]
    #读取大段文字

for line in data[:13]:  #返回14行的列表
    if line.strip():
        print(line)

或者简单一点:

with open('novels/天龙八部.txt',encoding='utf-8') as f:
    # 去掉结尾的换行符
    data = [line.strip() for line in f.readlines()]

for line in data[:13]:
    if line.strip():
        print (line)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值