在python2.7中,不同类型的对象(实例),如果其中一个比较对象是数字型(int/float/long/complex等),则数字型的对象<其它非数字型的对象(str,布尔型)
e.g.
'abc' > 100
返回值为 True。 而在Python 3.6 则为error 因为,非数字和数字无法比较。
2. str.lower()
str.upper() 把str这个字符串小写/大写
a = 'abc'
b = 'ABC'
print(a.upper())
print(b.lower())
3.
Python逻辑运算符
Python语言支持逻辑运算符,以下假设变量 a 为 10, b为 20:
运算符 | 逻辑表达式 | 描述 | 实例 |
---|---|---|---|
and | x and y | 布尔"与" - 如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。 | (a and b) 返回 20。 |
or | x or y | 布尔"或" - 如果 x 是非 0,它返回 x 的值,否则它返回 y 的计算值。 | (a or b) 返回 10。 |
not | not x | 布尔"非" - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。 | not(a and b) 返回 False |
所以 当我们看到 'b' == ('a' or 'b' or 'c') 其实并不是我们 想象中的 'b' =='a' or 'b' =='b' or 'b'=='c'
所以:
'b' == (0 or 'b')
True
小tips: maybe True 可以看作1 False 看作0
4. 字符串的index操作 超过范围会error 而切片操作超出范围并不会造成什么影响
e.g. s = 'abc' s[5] 得到的是 error
s[2:5] s[2:] 得到的都是 'c' s[3:5] 之类的 是 ''
5. 字符串比较大小
先比较两个对象的第0个元素,大小关系即为对象的大小关系,如果相等则继续比较后续元素,先终止迭代的认为是小的。
e.g. '333' >'22222' True 数字的永远比字母小 大写字母永远比小写的小 字母大小按 字母表 abcdef....z 排
6. 10 == 10.0 返回值是True
7.
字符串
字符串是以单引号'
或双引号"
括起来的任意文本,比如'abc'
,"xyz"
等等。请注意,''
或""
本身只是一种表示方式,不是字符串的一部分,因此,字符串'abc'
只有a
,b
,c
这3个字符。如果'
本身也是一个字符,那就可以用""
括起来,比如"I'm OK"
包含的字符是I
,'
,m
,空格,O
,K
这6个字符。
如果字符串内部既包含'
又包含"
怎么办?可以用转义字符\
来标识,比如:
'I\'m \"OK\"!'
表示的字符串内容是:
I'm "OK"!
转义字符\
可以转义很多字符,比如\n
表示换行,\t
表示制表符,字符\
本身也要转义,所以\\
表示的字符就是\
,可以在Python的交互式命令行用print()
打印字符串看看:
>>> print('I\'m ok.')
I'm ok.
>>> print('I\'m learning\nPython.')
I'm learning
Python.
>>> print('\\\n\\')
\
\
如果字符串里面有很多字符都需要转义,就需要加很多\
,为了简化,Python还允许用r''
表示''
内部的字符串默认不转义,可以自己试试:
>>> print('\\\t\\')
\ \
>>> print(r'\\\t\\')
\\\t\\
如果字符串内部有很多换行,用\n
写在一行里不好阅读,为了简化,Python允许用'''...'''
的格式表示多行内容,可以自己试试:
>>> print('''I
m love you''')
I
m love you
>>>
8.
当我们写:
a = 'ABC'
时,Python解释器干了两件事情:
在内存中创建了一个
'ABC'
的字符串;在内存中创建了一个名为
a
的变量,并把它指向'ABC'
。
Python支持多种数据类型,在计算机内部,可以把任何数据都看成一个“对象”,而变量就是在程序中用来指向这些数据对象的,对变量赋值就是把数据和变量给关联起来。
对变量赋值x = y是把变量x指向真正的对象,该对象是变量y所指向的。随后对变量y的赋值不影响变量x的指向。
9.
由于Python源代码也是一个文本文件,所以,当你的源代码中包含中文的时候,在保存源代码时,就需要务必指定保存为UTF-8编码。当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编码:
如果.py
文件本身使用UTF-8编码,并且也申明了# -*- coding: utf-8 -*-
,打开命令提示符测试就可以正常显示中文:
10.
格式化
最后一个常见的问题是如何输出格式化的字符串。我们经常会输出类似'亲爱的xxx你好!你xx月的话费是xx,余额是xx'
之类的字符串,而xxx的内容都是根据变量变化的,所以,需要一种简便的格式化字符串的方式。
在Python中,采用的格式化方式和C语言是一致的,用%
实现,举例如下:
>>> 'Hello, %s' % 'world'
'Hello, world'
>>> 'Hi, %s, you have $%d.' % ('Michael', 1000000)
'Hi, Michael, you have $1000000.'
你可能猜到了,%
运算符就是用来格式化字符串的。在字符串内部,%s
表示用字符串替换,%d
表示用整数替换,有几个%?
占位符,后面就跟几个变量或者值,顺序要对应好。如果只有一个%?
,括号可以省略。
常见的占位符有:
占位符 | 替换内容 |
---|---|
%d | 整数 |
%f | 浮点数 |
%s | 字符串 |
%x | 十六进制整数 |
其中,格式化整数和浮点数还可以指定是否补0和整数与小数的位数:
# -*- coding: utf-8 -*-Run
如果你不太确定应该用什么,%s
永远起作用,它会把任何数据类型转换为字符串:
>>> 'Age: %s. Gender: %s' % (25, True)
'Age: 25. Gender: True'
有些时候,字符串里面的%
是一个普通字符怎么办?这个时候就需要转义,用%%
来表示一个%
:
>>> 'growth rate: %d %%' % 7
'growth rate: 7 %'
format()
另一种格式化字符串的方法是使用字符串的format()
方法,它会用传入的参数依次替换字符串内的占位符{0}
、{1}
……,不过这种方式写起来比%要麻烦得多:
>>> 'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)
'Hello, 小明, 成绩提升了 17.1%'
11.
最后来看一个“可变的”tuple:
>>> t = ('a', 'b', ['A', 'B'])
>>> t[2][0] = 'X'
>>> t[2][1] = 'Y'
>>> t
('a', 'b', ['X', 'Y'])
这个tuple定义的时候有3个元素,分别是'a'
,'b'
和一个list。不是说tuple一旦定义后就不可变了吗?怎么后来又变了?
别急,我们先看看定义的时候tuple包含的3个元素:
当我们把list的元素'A'
和'B'
修改为'X'
和'Y'
后,tuple变为:
表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向'a'
,就不能改成指向'b'
,指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!
理解了“指向不变”后,要创建一个内容也不变的tuple怎么做?那就必须保证tuple的每一个元素本身也不能变。
12.
if
判断条件还可以简写,比如写:
if x:
print('True')
只要x
是非零数值、非空字符串、非空list等,就判断为True
,否则为False
。
13.
continue
在循环过程中,也可以通过continue
语句,跳过当前的这次循环,直接开始下一次循环。
n = 0
while n < 10:
n = n + 1
print(n)
上面的程序可以打印出1~10。但是,如果我们想只打印奇数,可以用continue
语句跳过某些循环:
n = 0
while n < 10:
n = n + 1
if n % 2 == 0: # 如果n是偶数,执行continue语句
continue # continue语句会直接继续下一轮循环,后续的print()语句不会执行
print(n)
执行上面的代码可以看到,打印的不再是1~10,而是1,3,5,7,9。
可见continue
的作用是提前结束本轮循环,并直接开始下一轮循环。
14.
函数可以返回多个值吗?答案是肯定的。
比如在游戏中经常需要从一个点移动到另一个点,给出坐标、位移和角度,就可以计算出新的新的坐标:
import math
def move(x, y, step, angle=0):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
import math
语句表示导入math
包,并允许后续代码引用math
包里的sin
、cos
等函数。
然后,我们就可以同时获得返回值:
>>> x, y = move(100, 100, 60, math.pi / 6)
>>> print(x, y)
151.96152422706632 70.0
但其实这只是一种假象,Python函数返回的仍然是单一值:
>>> r = move(100, 100, 60, math.pi / 6)
>>> print(r)
(151.96152422706632, 70.0)
原来返回值是一个tuple!但是,在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便。
15.
让 print 末尾不换行
print('a',end='') '' 表示以里面的东西 结尾 比如 ' ' 就是以空字符
print('Hello', end = " ")
print('world', end="?")
print('!')
Hello world?!
就像这个例子
16.
列表生成式 nested loop
下面这个程序 写成 列表生成式的形式:
flattened = [n for row in matrix for n in row]
注意不是:
flattened = [n for n in row for row in matrix]
When working with nested loops in list comprehensions remember that the for
clauses remain in the same order as in our original for
loops.
跟 for loop same order!
flattened = [] for row in matrix: for n in row: flattened.append(n)
17.把式子变得更好看一点
Note that we are not adding line breaks arbitrarily: we’re breaking between each of the lines of code we copy-pasted to make these comprehension. Our line breaks occur where color changes occur in the colorized versions.
其实就是 不管圆括号 中括号 大括号 你扩到下一行 没关系的
18. nonlocal :使用外层 (非全局)变量
global : 使用全局变量
闭包的特点就是 不执行内部定义的函数 而是等到要调用的时候再去执行。
Code:利用闭包返回一个计数器函数,每次调用它返回递增整数:
counterA = createCounter() print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5
def createCounter():
i=0
def counter():
nonlocal i
i +=1
return i
return counter
1.内部函数一般无法修改外部函数的参数
2.想要修改需要声明 nonlocal
3.内部函数可以修改外部list中的元素
4.对于createCounter来说i是局部变量,对于counter来说i是非全局的外部变量。内部函数若想修改外部函数中的外部变量,可以用nonlocal声明。而如果只是使用外部函数的外部变量,是不会报错的。
5.简单来说的话如果只是调用的话不需要额外的做出声明,但是要修改的话就要另当别论了
19.
20.
import xxx
是从 Python 系统库,或者项目的最外层导入 xxx
。from . import xxx
是从同一文件夹下导入 xxx
。from .yyy import xxx
是从当前目录的子文件夹 yyy
中导入 xxx
。
21. 可变对象和不可变对象
可变对象:
1.内存先创建一个空字典(A),然后x储存这个空字典的地址
2. y储存 x储存的地址 即空字典的地址
3. 修改这个空字典 (A) 把他变成 {'1': 2}
4. x,y 储存的 地址 指向的字典 没变 还是A
5. 内存 创建了 一个 新的空字典 (B), 然后x 储存的地址是 字典B
6. 而 y 储存的地址没变 还是A A的值也没变
7.所以 x 是 {} y是 {'1': 2}
不可变对象
-
没什么好说的
22. repr
描述
repr() 函数将对象转化为供解释器读取的形式。
语法
以下是 repr() 方法的语法:
repr(object)
参数
- object -- 对象。
返回值
返回一个对象的 string 格式。
实例
以下展示了使用 repr() 方法的实例:
>>> repr(s)
'[1, 2]'
>>> print(repr(s))
[1, 2]
>>> s = 'wang'
>>> print(repr(s))
'wang'
>>> print(s)
wang
>>>
repr就是把对象改是什么样 就变成什么样的字符串,所以如果原先是字符串 那么repr 之后就有 ' ' 引号
23.把一个list 变成dictionaries 的函数 比如 [1,1,2,'a'] 变成{1:2,2:1,'a':1}
def transdict(L):
dicts = {}
for i in L:
dicts.setdefault(i,0)
dicts[i] += 1
return dicts
24 max 巧用lambda
result = max(dict_1.items(),key=lambda x :x[-1])
这个函数啥意思呢 dict_1.items() 是要求 max 的 可迭代对象 而 key是 一个关键词参数 后面跟一个函数 没有括号 因为不是调用,这个 函数 的参数是 dict_1.items() 里的每一个元素 而lambda 是一个匿名函数 这个x是这个匿名函数的形参,冒号后面跟的时候这个函数返回值
25. 链式比较:a == b == c 跟 a<b<c 的顺序是一样的
都是 (a == b)and (b == c) (a<b) and (b<c)
所以咱们可以有
a == b != c:
a != b == c
但是我们要小心 (a==b) == c
这个就跟上面的不一样了 这个相当于 True 或者是 False 跟 c 比较了
26 打印 %
有些时候,字符串里面的%
是一个普通字符怎么办?这个时候就需要转义,用%%
来表示一个%
:
>>> 'growth rate: %d %%' % 7
'growth rate: 7 %'
27
默认参数很有用,但使用不当,也会掉坑里。默认参数有个最大的坑,演示如下:
先定义一个函数,传入一个list,添加一个END
再返回:
def add_end(L=[]):
L.append('END')
return L
当你正常调用时,结果似乎不错:
>>> add_end([1, 2, 3])
[1, 2, 3, 'END']
>>> add_end(['x', 'y', 'z'])
['x', 'y', 'z', 'END']
当你使用默认参数调用时,一开始结果也是对的:
>>> add_end()
['END']
但是,再次调用add_end()
时,结果就不对了:
>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']
很多初学者很疑惑,默认参数是[]
,但是函数似乎每次都“记住了”上次添加了'END'
后的list。
原因解释如下:
Python函数在定义的时候,默认参数L
的值就被计算出来了,即[]
,因为默认参数L
也是一个变量,它指向对象[]
,每次调用该函数,如果改变了L
的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]
了。
要修改上面的例子,我们可以用None
这个不变对象来实现:
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
现在,无论调用多少次,都不会有问题:
>>> add_end()
['END']
>>> add_end()
['END']
为什么要设计str
、None
这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。
28
在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。
我们以数学题为例子,给定一组数字a,b,c……,请计算a2 + b2 + c2 + ……。
要定义出这个函数,我们必须确定输入的参数。由于参数个数不确定,我们首先想到可以把a,b,c……作为一个list或tuple传进来,这样,函数可以定义如下:
def calc(numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
但是调用的时候,需要先组装出一个list或tuple:
>>> calc([1, 2, 3])
14
>>> calc((1, 3, 5, 7))
84
如果利用可变参数,调用函数的方式可以简化成这样:
>>> calc(1, 2, 3)
14
>>> calc(1, 3, 5, 7)
84
所以,我们把函数的参数改为可变参数:
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*
号。在函数内部,参数numbers
接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数:
>>> calc(1, 2)
5
>>> calc()
0
如果已经有一个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的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。