defdecorator3_with_args(*decorator_args): print(*decorator_args) #输出装饰器的参数 #在传参函数的内部再定义一个装饰器decorator3 defdecorator3(func): print("we are in decorator.") #在装饰器内部定义一个新的函数对象,作为装饰器的返回对象 defwrapper(*wrapper_args): print("we are in wrapper.") func(*wrapper_args) return wrapper return decorator3
Relative paths are relative to the working directory, not where the Python file is.
The working directory is the root of your terminal that runs your code with command (conda_env) Path\to\cwd>python code.py
The getcwd() function from the os module fetches the current working directory location. The function returns the full path starting from the root directory to the current working directory.
1 2
import os print(os.getcwd())
You can change the working directory using the os.chdir(<path>) method, and you can test whether a path, either directory, or file, exists using the os.path.exists(<path>) method.
Sub folder keeps the same working directory as main.
from package.module import returncwd print(returncwd()) # D:\Code\Python # Note: it is ~\Pthon not ~\Python\package
When debug in vscode, you can change the cwd by modifing the launch.json file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
{ "version":"0.2.0", "configurations":[ { "name":"Debug test", "type":"python", "request":"launch", "program":"${workspaceFolder}/test.py", "console":"integratedTerminal", "cwd":"${workspaceFolder}/package",// <-- change your cwd to the path that you // want your relative paths be relative to "justMyCode":true } ] }
double backslashes \\ & single forward slash /
Python treat a backslash (\) as an escape character. For instance, \n represents a line feed, and \t represents a tab. When specifying a path, a forward slash (/) can be used in place of a backslash. Two backslashes can be used instead of one to avoid a syntax error.
# elements() 方法按照元素首次出现的顺序, 列出所有元素 for element in counter.elements(): print(element) # A A A B B C # 可以使用 list() 转换成列表输出 print(list(counter.elements())) # ['A', 'A', 'A', 'B', 'B', 'C']
In Python, the time.time() function returns the number of seconds passed since epoch (the point where time begins).
What is epoch time?
Check this Epoch | wikiwand, you will have the answer.
Different systems have different epoch time.
For instance, Unix and POSIX measure time as the number of seconds that have passed since Thursday 1 January 1970 00:00:00 UT, a point in time known as the Unix epoch.
Windows NT systems, up to and including Windows 11 and Windows Server 2022, measure time as the number of 100-nanosecond intervals that have passed since 1 January 1601 00:00:00 UTC, making that point in time the epoch for those systems.
deffactorial(n): if n==0: return1 elif n>=1: return n*factorial(n-1)
defwaste(t): time.sleep(t)
if __name__ == "__main__": with cProfile.Profile() as profile: for i inrange(10): print(factorial(i)) waste(0.25) results = pstats.Stats(profile) results.sort_stats(pstats.SortKey.TIME) results.print_stats() # 87 function calls (42 primitive calls) in 2.581 seconds
for n inrange(2, 10): for x inrange(2, n): if n % x == 0: print( n, 'equals', x, '*', n/x) break else: # loop fell through without finding a factor print(n, 'is a prime number')
the imports can be done in the __init__.py, so it is more convenient to do the imports in the main.py.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# package/__init__.py if __name__ == '__main__': from moduleA import printA from subpack.moduleB import printB else: # use relative imports from .moduleA import printA from .subpack.moduleB import printB
# ----------------------------- # main.py
# from package.moduleA import printA # from package.subpack1.moduleB import printB from package import printA from package import printB
printA() # A printB() # B
Importing * From a Package
Besides, you can define a list named __all__ in the __init__.py, which contain the names of modules or methods that you have imported in the __init__.py. When you use from package import * in the main.py, all of the modules or methods in the __all__ list will be imported.
# package/__init__.py if __name__ == '__main__': from moduleA import printA from subpack.moduleB import printB else: # use relative imports from .moduleA import printA from .subpack.moduleB import printB
__all__ = ['printA', 'printB']
# ----------------------------- # main.py
# from package import printA # from package import printB from package import *
# moduleA.py from moduleB import funcB deffuncA(): funcB()
# ----------------------------- # moduleB.py from moduleA import funcA deffuncB(): funcA()
# ----------------------------- # main.py from moduleA import funcA
# ImportError: cannot import name 'funcA' from partially initialized # module 'moduleA' (most likely due to a circular import)
# ----------------------------- # main.py from moduleB import funcB # ImportError: cannot import name 'funcB' from partially initialized # module 'moduleB' (most likely due to a circular import)
If you want to get Recursion by importing two functions to call each other, you need use import ... instead of from ... import ....
Take the example in the following Recursion section for example
1 2 3 4 5 6 7 8 9 10 11 12 13 14
deffuncA(count): if count >= 10: return"A" else: return funcB(count+1)
deffuncB(count): if count >= 10: return"B" else: return funcA(count+1)
print(funcA(1)) # B print(funcB(1)) # A
The code above is a plain demonstration of Recursion. We split these two functions into two different modules, then import and call them in the main.py file.
deffuncB(count): if count >= 10: return"B" else: return moduleA.funcA(count+1)
# ----------------------------- # main.py from moduleA import funcA from moduleB import funcB
print(funcA(1)) # B print(funcB(1)) # A
Recursion
Python allows functions to call each other. By doing this, you will get a loop in your code, which is called Recursion. If you don’t define the conditions to end the loop, you will get a RecursionError, as what happened in the following code
1 2 3 4 5 6 7 8 9
deffuncA(): funcB()
deffuncB(): funcA()
funcA() # RecursionError: maximum recursion depth exceeded while calling # a Python object
To fix this problem, you need to define the condition of ending the recursion.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
deffuncA(count): if count >= 10: return"A" else: return funcB(count+1)
deffuncB(count): if count >= 10: return"B" else: return funcA(count+1)
print(funcA(1)) # B print(funcA(2)) # A print(funcB(1)) # A print(funcB(2)) # B
# package/subpack2/test.py # __name__ == '__main__' import sys # either way is ok sys.path.append(__file__+'\..\..') # sys.path.append(sys.path[0]+'\..')
# package/subpack2/test.py # __name__ == '__main__' import sys # either way is ok sys.path.append(__file__+'\..\..') # sys.path.append(os.path.join(sys.path[0], '..')) # sys.path.append(sys.path[0]+'\..')
# the first elmnt of sys.path is CWD # Current Working Directory print(sys.path[0]) # c:\Users\...\package\subpack2
# list.append(elmnt): # Add elmnt to the end of a list sys.path.append("..") # Print the last elmnt of sys.path print(sys.path[-1]) # ..
# list.insert(pos, elmnt): # Add elmnt to the head of a list (pos=0) sys.path.insert(0, "..") # Print the fitst elmnt of sys.path print(sys.path[0]) # ..
Common errors
ImportError
1
ImportError: attempted relative importwith no known parent package
# package/subpack2/test.py from .subsubpack.moduleD import printD # ImportError: attempted relative import with no known parent package
PEP 328 – Imports: Multi-Line and Absolute/Relative: Relative imports use a module’s __name__ attribute to determine that module’s position in the package hierarchy. If the module’s name does not contain any package information (e.g. it is set to '__main__') then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.
You can’t excute relative imports directly, the reasons are explained above, the module’s name does not contain any package information when __name__ == '__main__'.
If you call the modules containing relative imports in the programs under their parent folder, package/__init__.py or package/moduleA.py, the relative imports will be resolved correctly.
Because the __name__ == 'subpack2.test' in this case.
Two or more physical lines may be joined into logical lines using backslash characters (), as follows: when a physical line ends in a backslash that is not part of a string literal or comment, it is joined with the following forming a single logical line, deleting the backslash and the following end-of-line character. For example:
1 2 3 4
if1900 < year < 2100and1 <= month <= 12 \ and1 <= day <= 31and0 <= hour < 24 \ and0 <= minute < 60and0 <= second < 60: # Looks like a valid date return1
A line ending in a backslash cannot carry a comment. A backslash does not continue a comment. A backslash does not continue a token except for string literals (i.e., tokens other than string literals cannot be split across physical lines using a backslash). A backslash is illegal elsewhere on a line outside a string literal.
classStudent: name: str age: int def__init__(self, name:str, age:int) -> None: self.name = name self.age = age @classmethod deffrom_tuple_cls(cls, name_age: tuple) -> "Student": # "cls" means class itself, not an instance of the class like "self" name, age = name_age stu = cls(name, age) # <- Notice here return stu @staticmethod deffrom_tuple_stc(name_age: tuple) -> "Student": # there is no obligatory parameter like a "cls" or "self" name, age = name_age stu = Student(name, age) # <- Notice here return stu
(openmmlab)...>pip list ... Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/pip/ (Caused by SSLError (SSLZeroReturnError(6, 'TLS/SSL connection has been closed (EOF) (_ssl. c:1131)'))) - skipping
# numbers = range(100): # Processing 100 numbers took 0.3546745777130127 time using multiprocessing. # Processing 100 numbers took 0.0010056495666503906 time using serial processing. # numbers = range(1000): # Processing 1000 numbers took 0.33483433723449707 time using multiprocessing. # Processing 1000 numbers took 0.10793018341064453 time using serial processing. # numbers = range(10000): # Processing 10000 numbers took 2.137113571166992 time using multiprocessing. # Processing 10000 numbers took 11.323538064956665 time using serial processing.
print(f"Memery usage of multiprocessing: \n\t\ current size: {size_with_mp/(1024**2):.4f} MB, \ peak size: {peak_with_mp/(1024**2):.4f} MB") print(f"Memery usage of serialprocessing: \n\t\ current size: {size_without_mp/(1024**2):.4f} MB, \ peak size: {peak_without_mp/(1024**2):.4f} MB")
# Processing 1000 numbers took 0.3659026622772217 time using multiprocessing. # Processing 1000 numbers took 0.3618462085723877 seconds using serial processing. # Memery usage of multiprocessing: # current size: 1.3442 MB, peak size: 1.4158 MB # Memery usage of serialprocessing: # current size: 0.0009 MB, peak size: 0.0365 MB
python 指定类型
1 2
deffunction(x: "int|str", y: int|str) -> tuple: return x, y