python basic
great free learning website with quiz
great online editor & debugger
Zen of Python
By typing import this
, you can see the zen of python. Some need more explanation:
Explicit is better than implicit: It is best to spell out exactly what your code is doing. This is why adding a numeric string to an integer requires explicit conversion, rather than having it happen behind the scenes, as it does in other languages.
Flat is better than nested: Heavily nested structures (lists of lists, of lists, and on and on…) should be avoided.
Errors should never pass silently: In general, when an error occurs, you should output some sort of error message, rather than ignoring it.
PEP
Python Enhancement Proposals (PEP) are suggestions for improvements to the language, made by experienced Python developers.
PEP 8 is a style guide on the subject of writing readable code
PEP 20: The Zen of Python
PEP 257: Style Conventions for Docstrings
Naming conventions
PEP 8 is a style guide on the subject of writing readable code. It contains a number of guidelines in reference to variable names, which are summarized here:
- modules should have short, all-lowercase names;
- class names should be in the CapWords style;
- most variables and function names should be lowercase_with_underscores;
- constants (variables that never change value) should be CAPS_WITH_UNDERSCORES;
- names that would clash with Python keywords (such as ‘class’ or ‘if’) should have a trailing underscore.
install
Brew install
1 | $ brew install python |
install multiple version
1 | # use pyenv to install multiple version |
Other pythons installed:
- /usr/local/bin
- /usr/local/Cellar
pip
pip is the package installer for python.
1 | $ pip install package-name |
On windows, to use pip
after python installation, you need to config both the python & pip path.
1 | $ export PATH=$PATH:c/users/xiaoming/AppData/Programs/Python/Python37:c/users/xiaoming/AppData/Programs/Python/Python37/Scripts |
common used commands
1 | # list all installed packages |
Packaging
In Python, the term packaging refers to putting modules you have written in a standard format, so that other programmers can install and use them with ease.
This involves use of the modules setuptools and distutils.
organize existing files correctly. Place all of the files you want to put in a library in the same parent directory. This directory should also contain a file called _init_.py, which can be blank but must be present in the directory.
__init__.py
turns a directory to a module.
This directory goes into another directory containing the readme and license, as well as an important file called setup.py.1
2
3
4
5
6
7
8SoloLearn/
LICENSE.txt
README.txt
setup.py
sololearn/
__init__.py
sololearn.py
sololearn2.pyWrite the setup.py file. This contains information necessary to assemble the package so it can be uploaded to PyPI and installed with pip (name, version, etc.).
1
2
3
4
5
6
7setup(
name='SoloLearn',
version='0.1dev',
packages=['sololearn',],
license='MIT',
long_description=open('README.txt').read(),
)Write Other Files
Build a source distribution, use the command line to navigate to the directory containing setup.py, and run the command
python setup.py sdist
.- Run
python setup.py bdist
or, for Windows,python setup.py bdist_wininst
to build a binary distribution.
- Run
Upload the package to PyPI. Use
python setup.py register
, followed bypython setup.py sdist upload
to upload a package.install a package with
python setup.py install
.
Module
In Python, a module is a file containing Python code that defines functions, classes, and variables that can be used in other Python programs. Modules allow code organization, reusability, and encapsulation.
To use a module in your Python program, you need to import it using the import
statement. Here’s an example:
1 | # Importing the math module |
Python also allows you to import specific functions or variables from a module using the from ... import
statement. Here’s an example:
1 | # Importing specific functions from the math module |
You can also import a module with a different name using the as
keyword. This is useful when you want to provide a shorter or more descriptive alias for the module.
1 | # Importing the math module with an alias |
Python also supports creating your own modules by creating Python files with .py
extension. For example, let’s assume we have a file named my_module.py
containing the following code:
1 | # my_module.py |
We can then use this module in another Python program:
1 | # Importing a user-defined module |
In this case, we import the my_module
module and use the greet
function and my_variable
variable defined in that module.
Modules provide a way to organize and reuse code in Python, allowing you to break your program into smaller, manageable pieces. They help promote code modularity, readability, and maintainability.
python -m
The python -m
syntax is used to execute a module as a script using the Python interpreter. It allows you to run a Python module directly from the command line without explicitly specifying the module’s file path (This is the difference between python -m xxx
cand python /path/to/xxx.py
).
When you use the python -m
syntax, Python treats the specified argument as a module name and looks for that module in the module search path (sys.path
). It then executes the module as if it were a script.
Here’s an example to illustrate the usage of python -m
:
1 | python -m unittest discover -s tests -p '*_test.py' |
In this example, python -m unittest
is used to run the unittest
module as a script. The discover
command is passed as an argument to the unittest
module, and it is responsible for automatically discovering and running unit tests.
The -s tests
option specifies the starting directory for test discovery. In this case, it looks for tests in the tests
directory.
The -p '*_test.py'
option defines a pattern for discovering test files. It looks for files that end with _test.py
.
By using python -m
, you ensure that the unittest
module is executed as a script, regardless of the specific location of the unittest
module file.
This python -m
syntax is useful when working with Python modules that provide command-line interfaces or when you want to run a module as a standalone script without specifying the full path to the module’s file.
_init_.py
__init__.py
文件的作用是将文件夹变为一个Python模块,Python 中的每个模块的包中,都有__init__.py
文件。
通常__init__.py
文件为空,但是我们还可以为它增加其他的功能。我们在导入一个包时,实际上是导入了它的__init__.py
文件。这样我们可以在__init__.py
文件中批量导入我们所需要的模块,而不再需要一个一个的导入。
1 | # package |
注意这里访问__init__.py
文件中的引用文件,需要加上包名。
__init__.py
中还有一个重要的变量,__all__
, 它用来将模块全部导入。
1 | # __init__.py |
这时就会把注册在__init__.py
文件中__all__
列表中的模块和包导入到当前文件中来。
可以了解到,__init__.py
主要控制包的导入行为。
setup.py
setuptools is the packaging tool for python (like maven/gradle for java?)
When coding in local, you can use pip install
to install dependency. However, when deploy a python project, you need to package all dependency, modules into one project. You need setup.py
.
When organize python in modules, you need to know and import the function in other modules. In compilation stage, you need to feel the other modules&packages. setup.py
does the magic. (This is my guess)
Packaging for users
For normal users who don’t have python on computer, we need to convert scripts to executables for them.
For Windows, py2exe or PyInstaller or cx_Freeze can be used to package a Python script, along with the libraries it requires, into a single executable.
For Macs, use py2app, PyInstaller or cx_Freeze.
Some special grammars
if _name_ == ‘__main__’
如何简单地理解Python中的if _name_ == ‘__main__’
If you are test.py
, then other module knows you as __name__=='test'
, and you know yourself as __name=='__main__'
.
The code block in if __name__ == '__main__'
will only be executed when the file is executed directly. If other module import test.py
as module, the code block won’t be executed.
It’s kind of like main function in java/c, but with big difference. Python is a script language — interpretive execution, which can be run without any so-called main entry. You don’t need to make test.py
runnable by providing main
, but you can provide if __name__ == '__main__'
if you want this block only executed when called directly rather than as module.
else
The else statement can be used in:
- the if statement
- a for or while loop, the code within it is called if the loop finishes normally / completely (when a break statement does not cause an exit from the loop).
- the try/except statements, the code within it is only executed if no error occurs in the try statement.
1 | def if_else(a): |
class
Classes are created using the keyword class and an indented block, which contains class methods (which are functions). All methods must have self as their first parameter, you do not need to include it when you call the methods. Within a method definition, self refers to the instance calling the method.
To inherit a class from another class, put the superclass name in parentheses after the class name.
Classes can also have class attributes, created by assigning variables within the body of the class. These can be accessed either from instances of the class, or the class itself.
1 | class Animal: |
__new__
vs __init__
_new_ is a static method which creates an instance. It allocates memory for an object. __init__ initialize the value of the object (instance). __new__
is rarely overriden.
When you are instantiate an instance by calling the class, the __new__
gets called first to create the object in memory, and then __init__
is called to initialize it.
_new_ must return the created object. Only when __new__
returns the created instance then __init__
gets called. If __new__
does not return an instance then __init__
would not be called.
The __new__
definition:
1 | __new__(cls, *args, **kwargs) |
An example:
1 | import datetime as dt |
__del__
Destruction of an object occurs when its reference count reaches zero.
The del statement reduces the reference count of an object by one, and this often leads to its deletion.
The magic method for the del statement is __del__
.
1 | a = 5 |
private
The Python philosophy is often stated as “we are all consenting adults here”, meaning that you shouldn’t put arbitrary restrictions on accessing parts of a class. Hence there are no ways of enforcing a method or attribute be strictly private. However, there are ways to discourage people from accessing parts of a class, such as by denoting that it is an implementation detail, and should be used at their own risk.
Weakly private methods and attributes have a single underscore at the beginning. This signals that they are private, and shouldn’t be used by external code. Its only actual effect is that from module_name import * won’t import variables that start with a single underscore.
Strongly private methods and attributes have a double underscore at the beginning of their names. This causes their names to be mangled, which means that they can’t be accessed from outside the class by the name. The purpose of this isn’t to ensure that they are kept private, but to avoid bugs if there are subclasses that have methods or attributes with the same names. Basically, Python protects those members by internally changing the name to include the class name.
1 | class A: |
class methods vs instance methods vs static methods
Instance methods are called by a instance, which is passed to the self parameter of the method.
Class methods are called by a class, which is passed to the cls parameter of the method.
A common use of these are factory methods, which instantiate an instance of a class, using different parameters than those usually passed to the class constructor.
Class methods are marked with a classmethod decorator.
Static methods are similar to class methods, except they don’t receive any additional arguments; they are identical to normal functions that belong to a class.
They are marked with the staticmethod decorator.
1 | class Rectangle: |
Properties
Properties are created by putting the property decorator above a method, which means when the instance attribute with the same name as the method is accessed, the method will be called instead.
One common use of a property is to make an attribute read-only.
Properties can also be set by defining setter/getter functions.
The setter function sets the corresponding property’s value. To define a setter, you need to use a decorator of the same name as the property, followed by a dot and the setter keyword.
```python
class Pizza:
def init(self, a):
self._a = a
@property
def a_list(self):
return [self._a] * 10
@a_list.setter
def a_list(self, value):
self._a = value[0]
p = Pizza(7)
p.a_list # [7, 7, 7, 7, 7, 7, 7, 7, 7, 7]
p.a_list = [1]
p.a_list # [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
1 | ## Magic Methods |
__call__
method
__call__
method can call an object as a function. Thus you can transfer the object as a func parameter in a function.
1 | class PairNumber: |
__str__
vs __repr__
In short, the goal of __repr__
is to be unambiguous and __str__
is to be readable. If __repr__
is defined, and __str__
is not, the object will behave as though __str__=__repr__
.
The commandline will show the content in __repr__
when you simply type the object. And when print(some_obj), it will show the content in __str__
of that object. So many would say: __repr__
is for developers, __str__
is for customers. e.g. obj = uuid.uuid1(), obj._str__() is “2d7fc7f0-7706-11e9-94ae-0242ac110002” and obj.__repr_() is “UUID(‘2d7fc7f0-7706-11e9-94ae-0242ac110002’)”.
To sum up: implement __repr__
for any class you implement. This should be second nature. Implement __str__
if you think it would be useful to have a string version which errs on the side of readability.
See example in r method
Opening Files
You can specify the mode used to open a file by applying a second argument to the open function.
Sending “r” means open in read mode, which is the default.
Sending “w” means write mode, for rewriting the contents of a file.
Sending “a” means append mode, for adding new content to the end of the file.
Adding “b” to a mode opens it in binary mode, which is used for non-text files (such as image and sound files).
For example:
1 | # write mode |
You can use the + sign with each of the modes above to give them extra access to files. For example, r+ opens the file for both reading and writing.
Use
help(open)
to see the complete file modes supported.
“r”
Read from file - YES
Write to file - NO
Create file if not exists - NO
Truncate file to zero length - NO
Cursor position - BEGINNING“r+” ====> Opens a file for both reading and writing (write from the current cursor, that is, if you already call
file.read()
, then it means cursor is already at the end, then the writing is appending. However, if you start withfile.write()
, the cursor is at the beginning, thus it will rewrite from the beginning)
Read from file - YES
Write to file - YES
Create file if not exists - NO
Truncate file to zero length - NO
Cursor position - BEGINNING“w”
Read from file - NO
Write to file - YES
Create file if not exists - YES
Truncate file to zero length - YES
Cursor position - BEGINNING“w+” ===> Opens a file for both writing and reading
Read from file - YES
Write to file - YES
Create file if not exists - YES
Truncate file to zero length - YES
Cursor position - BEGINNING“a”
Read from file - NO
Write to file - YES
Create file if not exists - YES
Truncate file to zero length - NO
Cursor position - END“a+” ===> Opens a file for both appending and reading
Read from file - YES
Write to file - YES
Create file if not exists - YES
Truncate file to zero length - NO
Cursor position - END
Iterable containers
List/string/tuple slicing
slice can have 3 parameters:
- Start index (included, count from end of the list if negative, default as 0)
- End index (excluded, count from end of the list if negative, default as end of the list)
- Step
1 | str = '0123456' |
List Comprehensions
1 | cubes = [i**3 for i in range(5)] # [0, 1, 8, 27, 64] |
all & any
use all() / any() to check a list of bool.
1 | nums = [1,2,3,4,5] |
Tuple
1 | # define a tuple |
Generator
Generators are a type of iterable, like lists or tuples. Unlike lists, they don’t allow indexing with arbitrary indices, but they can still be iterated through with for loops.
They can be created using functions and the yield statement.
Using generators results in improved performance, which is the result of the lazy (on demand) generation of values, which translates to lower memory usage. Furthermore, we do not need to wait until all the elements have been generated before we start to use them.
1 | def spell(): |
Set
Sets can be combined using mathematical operations (list, tuple, dict do not support these operators)
The union operator | combines two sets to form a new one containing items in either.
The intersection operator & gets items only in both.
The difference operator - gets items in the first set but not in the second.
The symmetric difference operator ^ gets items in either set, but not both.
1 | s1 = {1,2,3,4,5} |
String format
1 | ####### hello world hello |
Functions
Function Arguments
Using *args
as a function parameter enables you to pass an arbitrary number of arguments to that function. The arguments are then accessible as the tuple args in the body of the function.
**kwargs (standing for keyword arguments) allows you to handle named arguments that you have not defined in advance. The keyword arguments return a dictionary in which the keys are the argument names, and the values are the argument values.
1 | def some_func(a, some_default='this is a default value', *args, **kwargs): |
Lambda
A lambda defines an anoymous function. It consists of the lambda keyword followed by a list of arguments, a colon, and the expression to evaluate and return.
1 | ## use named function |
Common used functors:
map, filter
module itertools is a standard library that contains several functions that are useful in FP.
One type of function it produces is infinite iterators.
The function count counts up infinitely from a value.
The function cycle infinitely iterates through an iterable (for instance a list or string).
The function repeat repeats an object, either infinitely or a specific number of times.
takewhile - takes items from an iterable while a predicate function remains true;
chain - combines several iterables into one long one;
accumulate - returns a running total of values in an iterable.
product - get possible combinations of some iterables
permutation - get permutation of an iterable
1 | from itertools import accumulate, takewhile, product, permutations |
Decorator
Decorators provide a way to modify functions using other functions.
Python provides support to wrap a function in a decorator by pre-pending the function definition with a decorator name and the @ symbol.
You can use a decorator if you want to modify more than one function in the same way. It’s the common template of multiple functions.
1 | from functools import wraps |
A single function can have multiple decorators. They are used from top to down. Everytime the original func is called, the current decorator is used.
1 | ## define anther two decorators |
Generator
see Iterable Containers / Generator above.
async/await
some links:
Fear and Awaiting in Async: A Savage Journey to the Heart of the Coroutine Dream - youtube
GitHub - dabeaz/curio: Good Curio! a library to separate the asynchronus world and synchronus world by the author of the above video.
async
create a coroutine which should be excuted when called. Use await
in an async function to hung up the coroutine itself until the awaited coroutine finished. await
can only be used in async
functions. The object after await
must be an Awaitable
(as long as you implement __await__()
, it’s an Awaitable
. Coroutine
extends from Awaitable
)
async
can be used anywhere except for:
lambda
list comprehension (available since python 3.6)
default methods (e.g.
__init__()
), but we can use metaclass to make__init__
awaitable.
eventloop
The essence of aysncio is an eventloop. All awaitables are added to the eventloop and wait for executing sequentially. If an event is interrupted by IO or sth, another event will be executed.
For every thread, it has its own eventloop. Events in different eventloops cannot communicate.
So basically, events in asyncio are executed sequentially, whereas their requests to IO may be paralled.
And the await
keyword means to emit the Awaitable event at once and the program will wait until it finishes. Thus if we want to emit two or more Awaitable events at almost the same time, we use asyncio.create_task(awaitable)
.
(function) create_task: (coro: Generator[Any, None, _T@create_task] | Coroutine[Any, Any, _T@create_task], *, name: str | None = …) -> Task[_T@create_task]
Schedule the execution of a coroutine object in a spawn task.
Return a Task object.
When using create_task
, the Awaitable is told to be emited as soon as possible.
1 | import asyncio |
async & decorator
1 | # 创建一个 anotation, 可以根据 function 是否在 async 环境运行 |
Awaitable & Coroutine class
The object after await
must be an Awaitable
(as long as you implement __await__()
, it’s an Awaitable
. Coroutine
extends from Awaitable
.
1 | # The abstract `Awaitable` and `Coroutine` class: |
Some convinent functions
help
: eg.help(Exception)
orhelp(e)
, to get the methods & data in a class/objectdir
: eg.dir(Exception)
ordir(e)
, is a simple version ofhelp
, shows all members as a stringinspect.getmro(type(e))
: get the class hierachy of a type
Major 3rd-Party Libraries
Django: The most frequently used web framework written in Python, Django powers websites that include Instagram and Disqus. It has many useful features, and whatever features it lacks are covered by extension packages.
CherryPy and Flask are also popular web frameworks.
BeautifulSoup is very useful when scraping data from websites, and leads to better results than building your own scraper with regular expressions.
A number of third-party modules are available that make it much easier to carry out scientific and mathematical computing with Python.
The module matplotlib allows you to create graphs based on data in Python.
The module NumPy allows for the use of multidimensional arrays that are much faster than the native Python solution of nested lists. It also contains functions to perform mathematical operations such as matrix transformations on the arrays.
The library SciPy contains numerous extensions to the functionality of NumPy.
Python can also be used for game development.
Usually, it is used as a scripting language for games written in other languages, but it can be used to make games by itself.
For 3D games, the library Panda3D can be used. For 2D games, you can use pygame.
# Issues
Make class method return self type
If you are using Python 3.10 or later, it just works. As of today (2019) in 3.7+ you must turn this feature on using a future statement (from __future__ import annotations
) - for Python 3.6 or below use a string.
Python 3.7+: from __future__ import annotations
1 | from __future__ import annotations |
Python <3.7: use a string
1 | class Position: |
Circular import
modify the position of import to fix the issues