44 KiB
Python
变量
在python中,可以通过如下方式创建变量:
message = "Hello Python Crash Course world!"
字符串
字符串首字母大写
name = "ada lovelace"
print(name.title())
字符串全部字符大写
name = "Ada Lovelace"
print(name.upper())
字符串全部字符小写
name = "Ada Lovelace"
print(name.lower())
字符串删除空白符
name = " Asahi Ogura `
# 删除左空白
name.lstrip()
# 删除右空白
name.rstrip()
# 删除左右空白
name.strip()
访问字符串中字符
ptyhon可以通过数组下标来访问字符串中的字符,如果字符串长度为n,那么索引范围为[0, n-1],同时,在python中还可以使用负数的索引,索引范围为[-n, -1]。
在python字符串中,第一个字符可以通过索引下标0和-n来访问,最后一个字符可以通过n-1和-1来访问。
字符串切片
字符串切片可以通过str[from:to:step]来标识,其标识下标为[from, to)范围内的子字符串,步长为step。
temp = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
其中,输出[0,10)范围内的字符串可以采用如下方式:
print(temp[0:10]) # ABCDEFGHIJ
print(temp[0:10:1]) # ABCDEFGHIJ
当步长被设置为2时,输出内容如下:
print(temp[0:10:2]) # ACEGI
正数索引和负数索引混用:
# 输出不包含末尾2个字符的子字符串
print(temp[0:-2]) # ABCDEFGHIJKLMNOPQRSTUVWX
print(temp[0:24]) # ABCDEFGHIJKLMNOPQRSTUVWX
print(temp[:-2]) # ABCDEFGHIJKLMNOPQRSTUVWX
# 输出末尾两个字符的子字符串
print(temp[-2:])
逆序输出字字符串
print(temp[::-1]) # ZYXWVUTSRQPONMLKJIHGFEDCBA
print(temp[-1:0:-1]) # ZYXWVUTSRQPONMLKJIHGFEDCBA
print(temp[25:0:-1]) # ZYXWVUTSRQPONMLKJIHGFEDCBA
字符串迭代
python中字符串可迭代,示例如下:
temp = "ABCDE"
for ind, ch in enumerate(temp):
print("ind = "+str(ind)+", ch = "+ch, end="\n")
# ind = 0, ch = A
# ind = 1, ch = B
# ind = 2, ch = C
# ind = 3, ch = D
# ind = 4, ch = E
数字
/
python中,整数执行/操作默认并不会进行整除,而是可能生成浮点数
print(3/2) # 1.5
//
python中,如果要执行整除,应该使用//运算符,该运算符为向下取整
print(3//2) # 1
print(-3//2) # -2
和java不同,java在执行整数除时,会舍弃掉小数部分,例如
-3/2,java中结果为-1,而python则是向下取整为-2如果python中
/操作想要和java保持一直,可以使用math中的trunc函数,math.trunc(-3/2)返回结果和java中一样,为-1
数字类型向字符串类型转换
可以通过str函数将数字类型转化为字符串类型
temp = 1.2
print("temp = "+str(temp))
列表
python中通过[e1, e2, ...]的形式来标识列表
访问列表中元素
可以通过数组下标的方式来访问列表中的元素
temp = [1, "2", "san"]
print(temp[1]) # 2
print(temp[-2]) # 2
列表元素操作
修改
temp = [1, "2", "san"]
temp[2] = 3.0
print(temp) # [1, '2', 3.0]
插入到末尾
如果想要向数组末尾插入元素,可以调用append方法
temp = [1, "2", "san"]
temp.append("four")
print(temp) # [1, '2', 'san', 'four']
在某位置之前插入
如果想要在特定位置之前插入元素,可以调用insert方法
temp = [1, "2", "san"]
temp.insert(1, "1.5")
print(temp) # [1, '1.5', '2', 'san']
temp.insert(4, "four")
print(temp) # [1, '1.5', '2', 'san', 'four']
删除列表中的元素
如果想要删除列表中的元素,可以通过del关键字进行删除
temp = [1, "2", "san"]
del temp[1]
print(temp) # [1, 'san']
列表与栈api
列表append操作是将元素追加到列表末尾,同时列表还支持pop操作,将列表末尾的元素作为栈顶元素弹出。
如果此时列表为空,那么调用pop方法将抛出异常
temp = [1, "2", "san"]
print(temp.pop()) # san
print(temp.pop()) # 2
print(temp.pop()) # 1
print(temp.pop()) # IndexError: pop from empty list
还可以为pop方法指定一个下标,此时可以弹出任何位置的元素
temp = [1, "2", "san"]
print(temp.pop(1)) # 2
print(temp.pop(0)) # 1
print(temp.pop(0)) # san
remove
在列表中,可以调用remove来移除列表中值为xxx的元素。
remove默认只会移除第一个匹配的元素
temp = [2, 1, 2, 1, 2]
temp.remove(2)
print(temp) # [1, 2, 1, 2]
列表排序
sort
可以通过sort方法针对列表中的元素进行排序,sort方法会该表列表中的元素顺序
temp = [2, 1, 2, 1, 2]
temp.sort()
print(temp) # [1, 1, 2, 2, 2]
如果想要逆向排序,可以为sort方法指定reverse=True
temp = [2, 1, 2, 1, 2]
temp.sort(reverse=True)
print(temp) # [2, 2, 2, 1, 1]
sorted
如果不想改变原列表中的元素顺序,而是生成一个排好序的新列表,可以调用sorted函数
temp = [2, 1, 2, 1, 2]
print(sorted(temp)) # [1, 1, 2, 2, 2]
print(sorted(temp, reverse=True)) # [2, 2, 2, 1, 1]
print(temp) # [2, 1, 2, 1, 2]
列表中顺序反转
如果不想对列表中元素进行排序,只是想逆序列表中的数据,可以调用reverse方法
temp = [2, 1, 2, 1, 3]
temp.reverse()
print(temp) # [3, 1, 2, 1, 2]
获取列表长度
可以通过len函数获取列表的长度
temp = [1,2,3]
temp.pop()
print(len(temp)) # 2
temp.pop()
print(len(temp)) # 1
temp.pop()
print(len(temp)) # 0
遍历列表
在python中,可以通过for ... in ...的形式来遍历列表中的元素
temp = [1, 2, 3]
for e in temp:
print(e)
# 1
# 2
# 3
range
在python中,可以通过range函数生成一系列数字,range(m,n)会生成[m,n)范围内的数字,可用于fori形式的遍历
arr = ["1", "3", "2"]
for ind in range(0, len(arr)):
print(arr[ind])
# 1
# 3
# 2
可以通过range函数来创建数字列表
print(list(range(0, 5))) # [0, 1, 2, 3, 4]
range也可以指定步长
print(list(range(0, 7, 2))) # [0, 2, 4, 6]
max, min, sum
针对数字型的列表,支持max、min、sum等函数来求最大值、最小值、总和
arr = list(range(1, 101))
print(max(arr)) # 100
print(min(arr)) # 1
print(sum(arr)) # 5050
根据一个列表生成另一个列表
python中,根据[expr(e) for e in list_a]的语法,可以快速根据一个列表得到应一个列表,目标列表中的每个元素都来源于来源列表的映射
arr = ['amd', 'nvidia']
graphic_msgs = ['fuck '+brand for brand in arr]
print(graphic_msgs) # ['fuck amd', 'fuck nvidia']
切片
列表的切片和字符串切片类似
arr = [1, 2, 3, 4, 5]
print(arr[::2]) # [1, 3, 5]
print([e**2 for e in arr[::2]]) # [1, 9, 25]
列表复制
在python中,如果要复制列表,可以创建整个列表的切片
arr = [1, 2, 3]
# 复制列表
arr_copied = arr[:]
print(arr_copied) # [1, 2, 3]
# 对复制后的列表进行写操作,并不会影响复制前的列表
arr_copied.pop()
print(arr_copied) # [1, 2]
print(arr) # [1, 2, 3]
元组
运行时列表中的元素可以被修改,如果想要让元素不可变,可以使用元组。
元组通过(e1, e2, e3, ...)形式来表示,和列表一样,元组也可以通过索引来访问。
但是元组中的元素无法复制,在执行赋值语句时会抛出异常。
pos = (50, 100)
pos[0] = 125 # TypeError:'tuple' object does not support item assignment
if
类似其他编程语言,python也支持if/else语法
cars = ['audi', 'bmw', 'subaru', 'toyota']
for car in cars:
if car == 'bmw':
print(car.upper())
else:
print(car.title())
and/or
python可以通过and和or操作符来拼接多个条件。
age = 179
is_alive = True
if age < 0 or age > 150 and is_alive:
print("age wired")
列表中是否包含某值
如果想要检查列表中是否包含特定值,可以采用xxx in list_a的语法。
arr = [1, 3, 2]
print(1 in arr) # True
列表中是否不包含某值
如果想要检查列表中是否不包含特定值,可以采用xxx not in list_a的语法。
arr = [1, 3, 2]
print(1 not in arr) # False
多分支if/elif/else
python可以通过if/elif/else的语法实现多分支判断
age = 40
if age < 20:
print("teen")
elif age < 40:
print("man")
else:
print("elder man")
字典
在python中,通过字典实现了其他语言中的Map数据结构。
dic = {"name": "Ogura Asahi", "age": 17}
print(dic['name']) # Ogura Asahi
向字典中添加键值对
dic = {"name": "Ogura Asahi", "age": 17}
dic['major'] = "student"
print(dic) # {'name': 'Ogura Asahi', 'age': 17, 'major': 'student'}
删除字典中的键值对
dic = {"name": "Ogura Asahi", "age": 17}
del dic['age']
print(dic) # {'name': 'Ogura Asahi'}
字典遍历
字典遍历可以通过for k, v in dic.items()的形式完成
dic = {"name": "Ogura Asahi", "age": 17}
for key, val in dic.items():
print("key = "+key+" , value = "+str(val))
如果只想遍历字典的key集合,可以通过for k in dic.keys()的方式
dic = {"name": "Ogura Asahi", "age": 17}
for key in dic.keys():
print("key = "+key)
如果只想遍历字典的value集合,可以通过for v in dic.values()的形式
dic = {"name": "Ogura Asahi", "age": 17}
for value in dic.values():
print("value = "+str(value))
按顺序遍历字典的key
通常,字典的key遍历顺序是不一定的。如果想要按排序后的顺序遍历key,可以采用如下方式:
dic = {"name": "Ogura Asahi", "age": 17}
for key in sorted(dic.keys()):
print("key = "+str(key))
while
i = 0
while i < 10:
print(i)
i += 1
函数
函数可通过如下方式来定义:
def fuck(brand, boss):
print("fuck you " + boss + " and your " + brand)
fuck("Nvidia", "Jensen Huang")
在调用函数时,可以打乱传入实参顺序,只需要传参时指定参数名称即可:
def fuck(brand, boss):
print("fuck you " + boss + " and your " + brand)
fuck(boss="Jensen Huang", brand="Nvidia")
参数默认值
声明函数时,可以为参数指定默认值,故而在调用函数时,可以对有默认值的参数进行省略
def fuck(boss, brand="Nvidia"):
print("fuck you " + boss + " and your " + brand)
fuck("Jensen Huang")
fuck(brand="Apple", boss="Cook")
接收多个参数
通过*paramTup的形式,python会将函数接收到的参数都存储在一个元组中。
def fuck(*name_list):
msg = "fuck "
is_head = True
for name in name_list:
if not is_head:
msg += ", "
is_head = False
msg += name
print(msg)
fuck("Nvidia", "Amd")
文件操作
文件读取
with open('pi_digits.txt') as file_object:
contents = file_object.read()
print(contents)
写入文件
filename = 'programming.txt'
with open(filename, 'w') as file_object:
file_object.write("I love programming.")
file_object.write("I love creating new games.")
文件末尾追加
filename = 'programming.txt'
with open(filename, 'a') as file_object:
file_object.write("I also love finding meaning in large datasets.\n")
file_object.write("I love creating apps that can run in a browser.\n")
module
在python中,支持将一些公用的实现放在一个文件中,在使用时可以在其他script中导入该文件并对公共实现进行调用。
此时,放置公共实现的文件称为module,module中的定义可以被其他module导入。
module是一个包含python定义和statement的文件,file name是module name加上.py。在module中,module name可以通过global变量__main__来进行访问。
module中可以包含executable statement和函数定义,statements则是为了初始化module。executable statement只会在module被初次import时执行。
每个module都会有其独有的private namespace,该namespace会用作module中所有函数的global namespace。故而,module的作者可以放心的在mdoule中使用global变量,module global变量有其自己的namespace,并不用担心module global变量和调用方的global变量发生冲突。
故而,可以通过modname.itemname来访问module中的global变量。
如果在module A中对module B执行了导入操作,那么被导入的module B中的names将会被全部添加到module A的global namespace中。
导入语法如下:
# 直接导入fibo中的names
from fibo import fib, fib2
fib(500)
# 从module中导入所有names,_开头的name不会被导入
from fibo import *
fib(500)
# 如果import语句后跟随了as,那么as后跟随的名称将会和被导入module绑定
import fibo as fib
fib.fib(500)
# 和上一个的效果相同,module通过`fibo`来引用
import fibo
from fibo import fib as fibonacci
fibonacci(500)
运行module
当想要运行module时,可以采用如下方法:
python fibo.py <arguments>
当有一段代码,只有当module以main module的情况下被调用时才会被执行,可以采用如下方式
if __name__ == '__main__':
# run some code
module search path
当module被导入时,python interpreter首先会在sys.builtin_module_names中搜寻module name,built-in-module-names中包含如下module:
>>> import sys
>>> sys.builtin_module_names
('_abc', '_ast', '_bisect', '_blake2', '_codecs', '_collections', '_csv', '_datetime', '_elementtree', '_functools', '_heapq', '_imp', '_io', '_locale', '_md5', '_operator', '_pickle', '_posixsubprocess', '_random', '_sha1', '_sha256', '_sha3', '_sha512', '_signal', '_socket', '_sre', '_stat', '_statistics', '_string', '_struct', '_symtable', '_thread', '_tracemalloc', '_warnings', '_weakref', 'array', 'atexit', 'binascii', 'builtins', 'cmath', 'errno', 'faulthandler', 'fcntl', 'gc', 'grp', 'itertools', 'marshal', 'math', 'posix', 'pwd', 'pyexpat', 'select', 'spwd', 'sys', 'syslog', 'time', 'unicodedata', 'xxsubtype', 'zlib')
>>>
如果builtin_module_names中不包含被导入的module name,那么其会在sys.path中寻找{module}.py文件,sys.path通过如下路径来初始化:
- input script所处的目录路径
PYTHONPATH全局变量,语法和PATH相同- 安装包默认位置
dir
通过内置的dir函数,可以输出module中的names
>>>import fibo, sys
>>>dir(fibo)
['__name__', 'fib', 'fib2']
>>>dir(sys)
['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__',
'__interactivehook__', '__loader__', '__name__', '__package__', '__spec__',
'__stderr__', '__stdin__', '__stdout__', '__unraisablehook__',
'_clear_type_cache', '_current_frames', '_debugmallocstats', '_framework',
'_getframe', '_git', '_home', '_xoptions', 'abiflags', 'addaudithook',
'api_version', 'argv', 'audit', 'base_exec_prefix', 'base_prefix',
'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing',
'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info',
'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info',
'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth',
'getallocatedblocks', 'getdefaultencoding', 'getdlopenflags',
'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile',
'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval',
'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
'intern', 'is_finalizing', 'last_traceback', 'last_type', 'last_value',
'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks',
'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'pycache_prefix',
'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth', 'setdlopenflags',
'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr',
'stdin', 'stdout', 'thread_info', 'unraisablehook', 'version', 'version_info',
'warnoptions']
当dir函数传参为空时,输出当前namespace的names
>>>a = [1, 2, 3, 4, 5]
>>>import fibo
>>>fib = fibo.fib
>>>dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
dir并不会输出内置的names,内置的names定义在builtinsmodule中:
>>>import builtins
>>>dir(builtins)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
'NotImplementedError', 'OSError', 'OverflowError',
'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
'__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit',
'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview',
'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars',
'zip']
package
假设python项目结构如下,package和子package中包含多个moduels:
sound/ Top-level package
__init__.py Initialize the sound package
formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
...
filters/ Subpackage for filters
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
在导入包时,会在sys.path中搜索package的子目录。
如果需要python将目录视为package,需要在目录下加入__init__.py文件,该文件可以为空。
使用者可以导入package中独立的模块:
import sound.effects.echo
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
from sound.effects import echo
echo.echofilter(input, output, delay=0.7, atten=4)
from ... import *
对于from {package} import *,其会查看是否包下定义的__init__.py文件中定义了__all__变量,如果定义了,那么会导入__all__中的所有module。
__all__ = ["echo", "surround", "reverse"]
异常处理
在python中,可以通过如下语法来进行异常处理
try:
# code block
pass
except ErrorType1:
# error type 1 handling code block
pass
except ErrorType2:
# error type 2 handling code block
pass
except Exception as result:
# handle other exception types
pass
else:
# code block that no error occurs
pass
finally:
# code block executed whether exception occurs
pass
抛异常
捕获异常后重新抛出异常
如果python在捕获异常后需要重新对异常进行抛出,可以使用raise关键字
try:
m = 10/0
except Exception as e:
print(e)
raise
finally:
print("handle correctly")
主动抛出异常
主动抛出异常时,也可使用raise关键字
try:
raise Exception("fucking Nvidia raised their price!")
except Exception as e:
print(e)
finally:
print("my wallet is empty!")
数据存储
json.dump
可以通过json.dump方法将内容以json的格式存储到文件中:
import json
def save_as_json(data, fd):
json.dump(data, fd)
waifu = {
"name": "Touma Kazusa",
"job": "Student",
"gender": "female",
"age": 17
}
is_save_success = True
try:
with open("shiro.json", "w") as shiro_fd:
save_as_json(waifu, shiro_fd)
except Exception as e:
print(e)
is_save_success = False
exit(1)
finally:
if is_save_success:
print("save success!")
json.load
可以通过json.load方法读取文件中的json格式内容:
import json
def read_as_json(fd):
return json.load(fd)
is_read_success = True
try:
with open("shiro.json", "r") as shiro_fd:
r_obj = read_as_json(shiro_fd)
print(r_obj)
except Exception as e:
print(e)
is_read_success = False
exit(1)
finally:
if is_read_success:
print("read success!")
http api
python安装requests包之后,可以访问http接口
import math
import requests
import time
try:
body = requests.get("https://api.m.taobao.com/rest/api3.do", {
"api": "mtop.common.getTimestamp"
}).json()
ts = body['data']['t']
t = time.localtime(math.trunc(int(ts) / 1000))
time_str = time.strftime("%Y-%m-%d %H:%M:%S %z", t)
print(time_str)
except Exception as e:
print(e)
raise
多线程
python可以通过引入threading和concurrent.futures两个包来引入多线程:
import math
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
import threading
import requests
ts_arr = []
lock = threading.Lock()
def query_ts():
try:
body = requests.get("https://api.m.taobao.com/rest/api3.do", {
"api": "mtop.common.getTimestamp"
}).json()
except Exception as e:
print(e)
raise
def query_ts_once():
ts_beg = time.time_ns()
query_ts()
ts_end = time.time_ns()
ts_spend = math.trunc((ts_end - ts_beg) / 1000000)
with lock:
ts_arr.append(ts_spend)
def stress_test(test_cnt):
with ThreadPoolExecutor(max_workers=32) as executor:
i = 0
f_list = []
while i < test_cnt:
f_t = executor.submit(query_ts_once)
f_list.append(f_t)
i += 1
as_completed(f_list)
stress_test(100)
print(f"max ts : {max(ts_arr)} ms")
print(f"min ts : {min(ts_arr)} ms")
print(f"avg ts : {sum(ts_arr) / len(ts_arr)} ms")
print(ts_arr)
linux命令交互
如果想要调用系统(linux)的命令,可以使用subprocess模块。
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None)
调用示例如下:
ret = subprocess.run(['ls', '-l'], capture_output=True, text=True)
print(ret.stdout)
输出如下:
total 4
-rwxrwxrwx 1 asahi asahi 110 May 4 03:18 main.py
-rwxrwxrwx 1 asahi asahi 73 May 4 01:10 shiro.json
drwxrwxrwx 1 asahi asahi 4096 Feb 7 21:39 venv
正则
python通过re模块提供了正则表达式的支持
match
match方法定义如下所示
re.match(pattern, string, flags=0)
match方法使用示例如下所示:
import re
def main():
match_res = re.match("(?P<prefix>.*) father", "i am your father")
if match_res is None:
print("failed match")
return
print(match_res.group("prefix")) # i am your
print(match_res.group(0)) # i am your father
main()
search
search方法定义如下所示
re.search(pattern, string, flags=0)
search方法使用示例如下所示
pattern
类似java,re提供了compile方法,返回正则编译后的pattern,并通过pattern执行操作
findall
pattern.findall方法会返回所有匹配的字符串
import re
def main():
msg = '''although i use amd graphic card, i view it as a trash for its bad performance in ai.
nvidia is also trash because its crazy price, fuck amd and nvidia!'''
pattern = re.compile("(amd|nvidia)\\s+(graphic card)?")
search_res_list = pattern.findall(msg)
print(search_res_list)
main()
# [('amd', 'graphic card'), ('nvidia', ''), ('amd', '')]
finditer
pattern.finditer会返回所有匹配的match对象
import re
def main():
msg = '''although i use amd graphic card, i view it as a trash for its bad performance in ai.
nvidia is also trash because its crazy price, fuck amd and nvidia!'''
pattern = re.compile("(amd|nvidia)\\s+(graphic card)?")
search_res_list = pattern.finditer(msg)
print([e.group(0) for e in search_res_list])
main()
# ['amd graphic card', 'nvidia ', 'amd ']
面向对象
命名空间
命名空间是name到对象的映射集合,在不同的命名空间中,相同name映射到的对象可能会不同。
namespace的示例有:
- 内置name集合:(包含内置异常名称和函数名,例如
abs()函数) - module中的global names
- 函数调用中的local names
在某种程度上来说,对象中的attributes也构成了一个命名空间
module
python支持将文件内容拆分到多个文件中,将function definition放置到文件中后,在其他文件或interactive instance中可以针对fucntion definition进行导入。
放置function definition的文件被称之为module,通常用来定义公共方法。
module name
module为包含python definition和statements的文件。file name由module name和.py后缀组成。在module中,module的名称可以通过全局变量名__name__进行访问。
如果在文件fibo.py中定义如下内容:
# Fibonacci numbers module
def fib(n):
"""Write Fibonacci series up to n."""
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
def fib2(n):
"""Return Fibonacci series up to n."""
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
那么fibomodule中的内容可以通过如下方式进行导入
import fibo
上述导入并不会将定义在fibomodule中的function name直接添加到当前的命名空间,其只是将module namefibo添加到了命名空间,可以通过module name访问module中定义的内容:
fibo.fib(1000)
fibo.fib2(100)
fibo.__name__
module statements
在module中除了可以包含function definition外,还可以包含可执行statements。该可执行statements用于对module进行初始化。
when statements will be executed
module中的statements只会在第一次该module被导入时执行。(如果module文件其本身被执行,而非作为依赖被其他文件导入,那么module中的statements也同样会被执行)
每个module都拥有其自己的private namespace,并且对于定义在module中的所有方法而言,private module既是global namespace。故而,作为module的开发者而言,其可以自由的使用global variables,而不用担心其global variables名称和module使用者定义的global variables发生冲突。
如果想要访问在module中定义的global variables,可以使用modname.itemname的方式。
通常而言,对于module的import被放置在文件的最外层最开始的部分,但这并非是必须的。在文件最外层被导入的module,其module name会被添加到当前文件的module glboal namespace中。
from ... import ...
import还存在一个变体,可以从module中直接导入name,而不是导入module后通过module name访问module中内容:
from fibo import fib, fib2
fib(500)
在上述示例中,fibo并没有被引入到当前文件的global namespace中。
除此之外,还可以导入module中所有的name
from fibo import *
fib(500)
同样的,fibo也不会被导入到当前global namespace中。
上述from fibo import *语句会导入fibomodule中定义的所有name,但是以下划线_开头的名称除外。
通常情况下,不要使用from fibo import *来进行导入,因为其引入的name是不确定的,可能会覆盖你所定义的部分内容。
as
在对其他module执行import操作时,可以通过as来进行重命名
import fibo as fib
fib.fib(500)
上述示例中,fib的名称将会绑定到module fibo。
from fibo import fib as fibonacci
fibonacci(500)
execute module as script
当想要将module作为script执行时,可以使用如下命令:
python fibo.py <arguments>
上述将module作为script执行的命令,和导入module时对module进行执行的行为实际上是一致的,唯一区别如下:
module作为script执行:__name__值为__main__module被导入:__name__值为module name
故而,在module中包含如下代码
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
可以使module既可作为module被导入,也可以作为可执行的脚本,其中该代码块只会在module作为main file时才会被执行。
并且,在module被导入时,sys并不会被导入。
module search path
当module名为spam的module被导入时,interpreter会按照如下顺序来进行查找:
- 首先,interpreter会从built-in module中查找
spam - 如果步骤1没有查询到,其会在
sys.path变量定义的路径中查找名为spam.py的文件
sys.path初始化
在python启动时,其会初始化module search path,初始化后的module search path可以通过sys.path来进行访问。
在sys.path中,组成如下:
sys.path中第一条entry是包含input script的目录(如果存在input script)- 若未指定input script,如
运行交互式shell、运行-c command、运行-m module时,sys.path的第一条entry则是当前目录
- 若未指定input script,如
PYTHONPATH环境变量中定义的路径也会被添加到search path中- 包含
standard python modules及其依赖的拓展modules的路径也会别添加到module search path中- 拓展modules在windows平台中后缀名为
.pyd,在其他平台中后缀名为.so - 其中,
standard python modules是平台无关的,被称为prefix extension modules则是平台相关的,被称为exec_prefix
- 拓展modules在windows平台中后缀名为
python支持通过
-c来直接运行python命令,示例如下python -c 'print(1+22*33)'python还支持通过
-m来直接运行module,示例如下echo '{"name":"John","age":30}' | python -m json.tool
部分系统支持symlinks,故而包含input script的目录路径会在input script的symlink被follow之后才进行计算。故而,
包含symlink的目录并不会被添加到sys.path中
在sys.path被初始化之后,python程序可以对sys.path进行修改。
在sys.path中,包含被运行文件的目录路径被放在了sys.path中最开始的位置,代表如果运行文件路径中如果存在和standard library module相同名称的文件,那么运行文件路径下的同名文件将会覆盖standard library module。
standard module
python附带了一个包含standard modules的library。standard modules中部分modules是内置在interpreter中的,built modules中的内容可能并不是语言核心操作的一部分,但是能够提供对操作系统的访问,例如系统调用等。
built-in modules中的module在不同平台是可选的,例如winreg module只存在于windows平台。但是,sysmodule在所有平台的python interpreter中都包含。
dir function
内置的dir()方法会查看在module中定义了哪些名称,其返回了一个sorted string list:
>>>import fibo, sys
>>>dir(fibo)
['__name__', 'fib', 'fib2']
>>>dir(sys)
['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__',
'__interactivehook__', '__loader__', '__name__', '__package__', '__spec__',
'__stderr__', '__stdin__', '__stdout__', '__unraisablehook__',
'_clear_type_cache', '_current_frames', '_debugmallocstats', '_framework',
'_getframe', '_git', '_home', '_xoptions', 'abiflags', 'addaudithook',
'api_version', 'argv', 'audit', 'base_exec_prefix', 'base_prefix',
'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing',
'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info',
'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info',
'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth',
'getallocatedblocks', 'getdefaultencoding', 'getdlopenflags',
'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile',
'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval',
'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
'intern', 'is_finalizing', 'last_traceback', 'last_type', 'last_value',
'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks',
'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'pycache_prefix',
'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth', 'setdlopenflags',
'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr',
'stdin', 'stdout', 'thread_info', 'unraisablehook', 'version', 'version_info',
'warnoptions']
当没有为dir()方法传递参数时,dir()方法会列出当前已经定义的名称:
>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
其列出的名称中包含所有类型:变量、module、function等
dir方法并不会列出内置的方法和变量,如果想要查看那些,可以使用dir(builtins)
import builtins
dir(builtins)
packages
packge是一种结构化python modules命名空间的方法,其使用了dotted module names。例如,module name为A.B其代表的是位于package A下的submodule B。
就像module可以使module的开发者们不用担心使用了和其他module中一样的变量/函数名一样,dotted module name可以令module的开发者不用担心使用了和其他module相同的module name。
如果,你要定义一系列的modules统一处理不同格式的sound files和sound data,可以采用如下的package结构:
sound/ Top-level package
__init__.py Initialize the sound package
formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
...
filters/ Subpackage for filters
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
当对package进行导入时,python会从sys.path中查询package的子目录。
其中,__init__.py文件用于让python将该目录看作是package。__init__.py文件可以是空文件,但是也可以包含对package进行初始化的代码或设置__all__变量。
在使用package中,可以单独导入package中的module:
import sound.effects.echo
上述示例中导入了sound.effects.echomodule,在对module进行使用时,必须采用如下方式指定mdoule的fullname:
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
另一种可选的导入方式如下:
from sound.effects import echo
在使用module时,只需要指定echo即可
echo.echofilter(input, output, delay=0.7, atten=4)
同时,也可以直接导入module中的方法:
from sound.effects.echo import echofilter
echofilter(input, output, delay=0.7, atten=4)
在使用import item.subitem.subsubitem这类语法时,除了最后的item外,其余item必须都要是package,最后的item可以是package或module,但不能是module中的内容。
import * from package
在对package执行import *的语法时,其导入行为准许如下规范:
- 如果package的
__init__.py文件中定义了__all__变量,其将认为__all__中定义了所有应该被import *所导入的module name
故而,package的开发者应当负责在package版本迭代时将__all__进行更新;当然,开发者页可以决定不对import *进行支持,不定义__all__。
示例如下,sound/effects/__init__.py中可能包含如下内容:
__all__ = ["echo", "surround", "reverse"]
其代表from sound.effect import *将会导入echo, surround, reverse三个module。
注意,本地定义的名称可能会遮挡submodules。例如,如果在sound/effects/__init__.py中定义了一个reverse函数,那么from sound.effects import *将只会导入echo, surround两个module。
__all__ = [
"echo", # refers to the 'echo.py' file
"surround", # refers to the 'surround.py' file
"reverse", # !!! refers to the 'reverse' function now !!!
]
def reverse(msg: str): # <-- this name shadows the 'reverse.py' submodule
return msg[::-1] # in the case of a 'from sound.effects import *'
如果在__init__.py中没有定义__all__,那么from sound.effects import *只会导入__init__.py中的其他定义内容,示例如下:
import sound.effects.echo
import sound.effects.surround
from sound.effects import *
包内部相互引用
在同一个包中,不同subpackage中的module可以对彼此进行引用。引用支持绝对路径和相对路径,例如,sound.filters.vocoder在对sound.effects中定义的包进行import时,可以采用如下方式:
- 绝对路径:
from sound.effects import echo - 相对路径:
from ..effects import echo
在使用相对路径的导入时,示例如下:
当从surround执行相对路径导入时,可以执行如下形式的导入
from . import echo # 位于相同的subpackage中
from .. import formats # 访问../formats
from ..filters import equalizer # 访问../filters中的equalizer