python学习
range()函数
range(5) -> 0、1、2、3、4
range(5,9) -> 5、6、7、8
range(0,10,3) -> 0、3、6、9 :步长为3
列表
在内存中,序列是一块用来存储多个值的连续的内存空间。
一个对象包含:内存地址id,数据类型type,数值value三部分,序列中存储的是对象的id。
列表索引,从前往后,下标从0开始,从后往前,下标从-1开始。
list.append(obj) #在列表末尾添加新的对象
list.extend(seq) #在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
list.count(obj) #统计某个元素在列表中出现的次数
list.index(obj) #从列表中找出某个值第一个匹配项的索引位置
list.insert(index, obj) #将对象插入列表index位置
list.pop([index=-1]) #移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
list.remove(obj) #移除列表中某个值的第一个匹配项
list.sort( key=None, reverse=False) #对原列表进行排序
list.clear() #清空列表
list.copy() #复制列表,返回列表对象的浅拷贝
list.reverse() #所有元素原地翻转
append()方法是原地增加元素,列表内存地址不变
>>> list2=[x**2 for x in range(10) if x&1==1]
>>> list2
[1, 9, 25, 49, 81]
>>> id(list2)
22112552
>>> list2.append(2)
>>>> list2
[1, 9, 25, 49, 81, 2]
>>> id(list2)
22112552
+运算使用新内存地址,而+=运算仍使用原内存地址
>>> list3
[1, 2, 3, 4, 5]
>>> id(list3)
22111464
>>> list3+=[6]
>>> list3
[1, 2, 3, 4, 5, 6]
>>> id(list3)
22111464
>>> list3=list3+[7]
>>> list3
[1, 2, 3, 4, 5, 6, 7]
>>> id(list3)
22069096
extend()方法是原地操作,内存地址不变。效率高于+运算的拼接操作。
>>> list3.extend([9,10])
>>> list3
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> id(list3)
22069096
列表删除:
del 直接删除
del list[2]
pop() 删除并返回,如未指定位置,默认删除最后一个元素
>>> list4=[1,2,3,4]
>>> list4
[1, 2, 3, 4]
>>> del list4[2]
>>> list4
[1, 2, 4]
>>> list4.pop()
4
>>> list4
[1, 2]
remove()方法,删除首次出现的指定元素,若不存在,抛出异常。
>>> list5=[1,2,3,4,5,4,3,2]
>>> list5.remove(2)
>>> list5
[1, 3, 4, 5, 4, 3, 2]
>>> list5.remove(6)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
列表索引:
index()方法,获取指定元素首次出现的位置,可指定搜索的起始地址。
def index(self, *args, **kwargs): # real signature unknown
"""
Return first index of value.
Raises ValueError if the value is not present.
"""
pass
>>>list1=[1,2,3,4,5,3,4,6]
>>>print(list1.index(3,4))
不建新对象的列表排序:
>>> list6=[1,6,4,9,20,8,3]
>>> id(list6)
22112616
>>> list6.sort()
>>> list6
[1, 3, 4, 6, 8, 9, 20]
>>> id(list6)
22112616
>>> list6.sort(reverse=True)
>>> list6
[20, 9, 8, 6, 4, 3, 1]
>>> id(list6)
22112616
打乱顺序:
>>> import random
>>> random.shuffle(list6)
>>> list6
[3, 8, 20, 4, 1, 6, 9]
>>> id(list6)
22112616
sorted()函数排序,生成新对象:
>>> list6=sorted(list6)
>>> list6
[1, 3, 4, 6, 8, 9, 20]
>>> id(list6)
22036296
列表推导式生成
cells = [(row,col) for row in range(1,10) for col in range(1,10)]
#可以加两个循环,实际是个嵌套循环,cells列表包含9*9个元组
元组
元组中只包含一个元素时,需要在元素后面添加逗号‘ , ’,否则括号会被当作运算符使用。
元组可以使用下标索引来访问元组中的值。
元组中的元素值是不允许修改的,但我们可以对元组进行连接组合。
元组中的元素值是不允许删除的,但我们可以使用del语句来删除整个元组。
len(tuple) #计算元组元素个数。
max(tuple) #返回元组中元素最大值。
min(tuple) #返回元组中元素最小值。
tuple(iterable) #将可迭代系列转换为元组。
>>>list1= ['Google', 'Taobao', 'Runoob', 'Baidu']
>>>tuple1=tuple(list1)
>>>tuple1
('Google', 'Taobao', 'Runoob', 'Baidu')
所谓元组的不可变指的是元组所指向的内存中的内容不可变。
不可变对象,如元组,其中若包含可变对象,如列表,则对列表内容的修改是合法的。元组中存放的是列表的内存地址,列表元素的改变并不改变其自身的地址。
元组排序只能用sorted()函数,且返回类型为列表
>>> tup=(1,5,4,9,8,7,3,6)
>>> id(tup)
21784752
>>> type(tup)
<class 'tuple'>
>>> list=sorted(tup)
>>> id(list)
22112616
>>> type(list)
<class 'list'>
>>> list
[1, 3, 4, 5, 6, 7, 8, 9]
zip()函数:
>>> list1=[1,2,3]
>>> list2=[10,20,30]
>>> list3=[100,200,300]
>>> zip_tup=zip(list1,list2,list3)
>>> type(zip_tup)
<class 'zip'>
>>> list(zip_tup)
[(1, 10, 100), (2, 20, 200), (3, 30, 300)]
生成器推导式(用于生成元组)
>>> (x for x in range(1,100) if x%0==0)
<generator object <genexpr> at 0x013269C8>
推导式得到的是生成器对象。
一个生成器只能运行一次。
>>> generator = (x for x in range(1,100) if x%3==0)
>>> tup1=tuple(generator)
>>> tup1
(3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99)
>>> tup2=tuple(generator)
>>> tup2
()
字典
- 访问字典里的值
把相应的键放入到方括号中,如下实例:
tinydict = {'Name': 'xiaoming', 'Age': 10, 'Class': 'First'}
print ("tinydict['Name']: ", tinydict['Name'])
print ("tinydict['Age']: ", tinydict['Age'])
运行结果:
tinydict['Name']: xiaoming
tinydict['Age']: 10
- 使用大括号 { } 创建空字典
# 使用大括号 {} 来创建空字典
emptyDict = {}
# 打印字典
print(emptyDict)
# 查看字典的数量
print("Length:", len(emptyDict))
# 查看类型
print(type(emptyDict))
运行结果:
{}
Length: 0
<class 'dict'>
- 向字典添加新内容的方法是增加新的键/值对,修改或删除已有键/值对如下实例:
tinydict = {'Name': 'xiaoming', 'Age': 10, 'Class': 'First'}
tinydict['Age'] = 8 # 更新 Age
tinydict['School'] = "一中" # 添加信息
print ("tinydict['Age']: ", tinydict['Age'])
print ("tinydict['School']: ", tinydict['School'])
- 能删单一的元素也能清空字典,清空只需一项操作。显式删除一个字典用del命令
tinydict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
del tinydict['Name'] # 删除键 'Name'
tinydict.clear() # 清空字典
del tinydict # 删除字典
tinydict.pop('Name') #删除键值对,并返回值
print ("tinydict['Age']: ", tinydict['Age'])
print ("tinydict['School']: ", tinydict['School'])
- 字典值可以是任何的 python 对象,既可以是标准的对象,也可以是用户定义的,但键不行。
两个重要的点需要记住:
1)不允许同一个键出现两次。创建时如果同一个键被赋值两次,后一个值会被记住
tinydict = {'Name': 'Lisa', 'Age': 26, 'Name': '丽莎'}
print ("tinydict['Name']: ", tinydict['Name'])
运行结果:
tinydict['Name']: 丽莎
2)键必须不可变,所以可以用数字,字符串或元组充当,而用列表就不行,如下实例:
tinydict = {['Name']: 'Runoob', 'Age': 7}
print ("tinydict['Name']: ", tinydict['Name'])
以上实例输出结果:
Traceback (most recent call last):
File "C:/Users/11457/Desktop/pythonProject1/practise.py", line 1, in <module>
tinydict = {['Name']: 'Runoob', 'Age': 7}
TypeError: unhashable type: 'list'
- 相关函数:
len(dict) #计算字典元素个数,即键的总数。
str(dict) #输出字典,可以打印的字符串表示。
dict.update(dict2) #更新dict2的键值对到dict上
字典对象的核心是散列表。
字典的遍历操作与字典的修改操作分开,新增键值对可能导致字典扩容,键值对顺序重排。
字典推导式
>>> my_text='i love you,i love him,i love all people.'
>>> char_count={c:my_text.count(c) for c in my_text}
>>> char_count
{'i': 4, ' ': 7, 'l': 6, 'o': 5, 'v': 3, 'e': 5, 'y': 1, 'u': 1, ',': 2, 'h': 1, 'm': 1, 'a': 1, 'p': 2, '.': 1}
- 有序哈希表中的键值对是按照插入顺序排序。Python 3.6 后,默认字典就是有序的,因此无需使用
OrderedDict()
。
集合
集合的底层实现是字典,实际是字典中的键对象。
集合set1和set2:
并集
set1|set2
交集
set1&set2
差集
set1-set2
集合推导式生成
>>> set1={x for x in range(1,100) if x%11==0}
>>> set1
{33, 66, 99, 11, 44, 77, 22, 55, 88}
字符串
字符串切片
s='abcdef'
>>> s[2:]
'cdef'
>>> s[2:5]
'cde'
>>> s[:-2]
'abcd'
>>> s[::-1]
'fedcba'
split()函数
>>> str='i am a teacher'
>>> str
'i am a teacher'
>>> str.split()
['i', 'am', 'a', 'teacher']
>>> str.split('a')
['i ', 'm ', ' te', 'cher']
join()函数
>>> str=['as','bg','DG','Ui']
>>> '*'.join(str)
'as*bg*DG*Ui'
>>> ''.join(str)
'asbgDGUi'
>>> ' '.join(str)
'as bg DG Ui'
+操作字符串,有几个+,就生成几个新字符串对象,join()的性能好。
字符串驻留机制
>>> a='abc123'
>>> b='abc123'
>>> print(id(a),id(b))
30500256 30500256
相关函数
>>> str1='我是mary,今天我来到这里,很开心。'
>>> str1.startswith('我') #判断是否以'我'开始
True
>>> str1.endswith('心。') #判断是否以'心。'结束
True
>>> str1.find('我') #'我'第一次出现的位置
0
>>> str1.rfind('我')#'我'最后一次出现的位置
9
>>> str1.find('s') #查询不存在的字符的位置,返回-1
-1
>>> len(str1) #字符串长度
19
>>> str1.isalnum() #字符串全是字母与数字
False
>>> str1.isalpha() #字符串全是字母
False
>>> str1.count('我')#统计'我'出现了几次
2
>>> ' acount number '.strip() #去除首尾空格
'acount number'
>>> ' acount number '.lstrip() #去除首部空格
'acount number '
>>> ' acount number '.rstrip() #去除尾部空格
' acount number'
>>> '**#$asdfghk%^*'.strip('*') #去除首尾'*'
'#$asdfghk%^'
大小写转换
>>> str2='i like my home'
>>> str2.capitalize() #产生新字符串,首字母大写
'I like my home'
>>> str2.title() #产生新字符串,每个单词首字母大写
'I Like My Home'
>>> str2.upper() #产生新字符串,每个字母都大写
'I LIKE MY HOME'
>>> str3='I LIKE MY HOME'
>>> str3.lower() #产生新字符串,每个字母都小写
'i like my home'
>>> str4='I LiKe My HouSE'
>>> str4.swapcase() #产生新字符串,所有字母大小写改变
'i lIkE mY hOUse'
字符串的格式化
format()函数
可变字符串 StringIO
>>> import io
>>> s='hello,world'
>>> sio=io.StringIO(s)
>>> sio
<_io.StringIO object at 0x017B8898>
>>> sio.getvalue()
'hello,world'
>>> sio.seek(7)
7
>>> sio.seek(0)
0
>>> sio.write('H')
1
>>> sio.getvalue()
'Hello,world'
##运算符
| #按位或
& #按位与
^ #按位异或
~ #按位翻转
<< #左移位
>> #右移位
/ #除
// #整除
+ #数字相加;字符串拼接;列表、元组合并
* #数字相乘;字符串复制;列表、元组复制
函数
在函数中使用全局变量,需要先用global声明。
局部变量的查询与访问速度高于全局变量。
参数传递
python中一切皆对象,所有的参数传递都是‘引用传递’,没有‘值传递’。
b=[10,20,30]
print("b:",id(b))
def funcb(m):
print("m:",id(m))
m.append(40)
funcb(b)
print(b)
print('b:',id(b))
运行结果:
b: 25339368
m: 25339368
[10, 20, 30, 40]
b: 25339368
传递不可变类型对象时,仍是引用传递,当函数内对该对象修改时,才创建新对象。
a=10
print("a:",id(a))
def funcb(m):
print("m:",id(m))
m+=1
print("m:",id(m))
funcb(a)
结果:
a: 1682950208
m: 1682950208
m: 1682950224
默认值参数应放在形参列表的后面部分。
浅拷贝与深拷贝
浅拷贝:不拷贝子对象的内容,只拷贝子对象的引用。
深拷贝:连子对象的内存页全部拷贝一份,对子对象的修改不影响源对象。
传递不可变对象时,如果发生拷贝(赋值时),是浅拷贝。
浅拷贝示例代码:
import copy
a=[10,20,[30,40]]
b=copy.copy(a)
print('a',a,id(a))
print('b',b,id(b))
b.append(50)
b[2].append(0)
print('---浅拷贝---')
print('a',a,id(a))
print('b',b,id(b))
结果:
```python
a [10, 20, [30, 40]] 29937256
b [10, 20, [30, 40]] 29937064
---拷贝---
a [10, 20, [30, 40, 0]] 29937256
b [10, 20, [30, 40, 0], 50] 29937064
深拷贝示例代码:
import copy
a=[10,20,[30,40]]
b=copy.deepcopy(a)
print('a',a,id(a))
print('b',b,id(b))
b.append(50)
b[2].append(0)
print('---深拷贝---')
print('a',a,id(a))
print('b',b,id(b))
结果:
a [10, 20, [30, 40]] 27446888
b [10, 20, [30, 40]] 27446696
---深拷贝---
a [10, 20, [30, 40]] 27446888
b [10, 20, [30, 40, 0], 50] 27446696
可变参数与强制命名参数
可变参数分为两种,其一为*param,收集实参至元组中;其二为**param,收集实参至字典中。
*param:
def func1(a,b,*c):
print(a,b,c)
func1(1,2,3,4,5,6,'a')
运行结果:
1 2 (3, 4, 5, 6, 'a')
**param:
def func1(a,b,**c):
print(a,b,c)
func1(1,2,name='zzq',age=19,school='dlut')
运行结果:
1 2 {'name': 'zzq', 'age': 19, 'school': 'dlut'}
嵌套函数
nonlocal 声明外层局部变量,之后可对其修改。
global 声明全局变量,之后可对其修改。
yield关键字
返回用yield不用return,函数返回一个生成器。
迭代器与可迭代性
迭代器:能用next()访问,并不断返回下一个值的对象。
Interable:可迭代性
Interaor:迭代器
集合类对象(list,str,tuple,dict)与生成器都是可迭代的,但未必都是迭代器。
iter()函数:将具有迭代性的对象变为生成器对象,可使用next()函数。
闭包
是特殊函数,创建时很特殊。
是函数式编程的重要方式。
创建闭包:
- 嵌套函数定义(内部函数、外部函数)。
- 内部函数使用外部函数中定义的变量。
- 外部函数一定要有返回值,返回内部函数名。
简单例子:
def funcOut(num1):
def funcIn(num2):
return num2+num1
return funcIn
if __name__ == '__main__':
a=10
b=20
f=funcOut(a)
print(type(f))
print(f(b))
print(f(100))
<class 'function'>
30
110
外部函数的局部变量,不会随着外部函数调用结束而消失。
闭包的特殊用途:
- 可以在不修改现有功能源码的前提下,增加新的功能。如:
日志功能(统计访问事件,访问功能,写到日志文件),权限验证
外部声明
global:全局声明
nonlocal:外部声明
类与对象
new()方法:创建对象,一般不需要重写
init()方法:初始化创建好的对象,一般需要自己重写
私有属性
class Employee:
def __init__(self,name,age):
self.name=name
self.__age=age #属性前加__,表示私有
e=Employee('xiaoming',18)
print(e.name)
print(e._Employee__age) #类外部访问私有属性的格式
运行结果:
xiaoming
18
父类的私有属性,子类也需要间接访问。
组合
class A:
def say(self):
print('AAA')
class B:
def __init__(self,a):
self.a=a
a=A()
b=B(a)
b.a.say()
运行结果
AAA
模块与包
__init__.py
:包中模块首次被使用时,__init__.py
模块会执行一次。
输入输出
input()
input()函数得到的是str型,像作为其他类型使用,如int型,需转换