Files
rikako-note/python/py.md

34 KiB
Raw Blame History

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/2java中结果为-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可以通过andor操作符来拼接多个条件。

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中导入该文件并对公共实现进行调用。

此时放置公共实现的文件称为modulemodule中的定义可以被其他module导入。

module是一个包含python定义和statement的文件file namemodule 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 namebuilt-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方法定义如下所示

re.search(pattern, string, flags=0)

search方法使用示例如下所示

pattern

类似javare提供了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并不会被导入。