diff --git a/python/py.md b/python/py.md index 017411c..50623c6 100644 --- a/python/py.md +++ b/python/py.md @@ -51,6 +51,12 @@ - [文件读取](#文件读取) - [写入文件](#写入文件) - [文件末尾追加](#文件末尾追加) + - [module](#module) + - [运行module](#运行module) + - [module search path](#module-search-path) + - [dir](#dir) + - [package](#package) + - [from ... import \*](#from--import-) - [异常处理](#异常处理) - [抛异常](#抛异常) - [捕获异常后重新抛出异常](#捕获异常后重新抛出异常) @@ -67,6 +73,8 @@ - [pattern](#pattern) - [findall](#findall) - [finditer](#finditer) + - [面向对象](#面向对象) + - [命名空间](#命名空间) # Python @@ -575,6 +583,195 @@ 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中。 + +导入语法如下: + +```python +# 直接导入fibo中的names +from fibo import fib, fib2 +fib(500) +``` + +```python +# 从module中导入所有names,_开头的name不会被导入 +from fibo import * +fib(500) +``` + +```python +# 如果import语句后跟随了as,那么as后跟随的名称将会和被导入module绑定 +import fibo as fib +fib.fib(500) +``` + +```python +# 和上一个的效果相同,module通过`fibo`来引用 +import fibo +``` + +```python +from fibo import fib as fibonacci +fibonacci(500) +``` +### 运行module +当想要运行module时,可以采用如下方法: +```bash +python fibo.py +``` +当有一段代码,只有当module以main module的情况下被调用时才会被执行,可以采用如下方式 +```python +if __name__ == '__main__': + # run some code +``` + +### module search path +当module被导入时,python interpreter首先会在`sys.builtin_module_names`中搜寻module name,built-in-module-names中包含如下module: +```ptyhon3 +>>> 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 +```bash +>>>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 +```bash +>>>a = [1, 2, 3, 4, 5] +>>>import fibo +>>>fib = fibo.fib +>>>dir() +['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys'] +``` +dir并不会输出内置的names,内置的names定义在`builtins`module中: +```bash +>>>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中独立的模块: +```python +import sound.effects.echo +sound.effects.echo.echofilter(input, output, delay=0.7, atten=4) +``` + +```python +from sound.effects import echo +echo.echofilter(input, output, delay=0.7, atten=4) +``` +#### from ... import * +对于`from {package} import *`,其会查看是否包下定义的`__init__.py`文件中定义了`__all__`变量,如果定义了,那么会导入`__all__`中的所有module。 + +```python +__all__ = ["echo", "surround", "reverse"] +``` + ## 异常处理 在python中,可以通过如下语法来进行异常处理 ```py @@ -832,4 +1029,18 @@ def main(): main() # ['amd graphic card', 'nvidia ', 'amd '] -``` \ No newline at end of file +``` + +## 面向对象 +### 命名空间 +命名空间是name到对象的映射集合,在不同的命名空间中,相同name映射到的对象可能会不同。 + +namespace的示例有: +- 内置name集合:(包含内置异常名称和函数名,例如`abs()`函数) +- module中的global names +- 函数调用中的local names + +> 在某种程度上来说,对象中的attributes也构成了一个命名空间 + + +