mirror of
https://github.com/kennethreitz/python-guide.git
synced 2026-06-05 23:00:18 +00:00
@@ -104,26 +104,38 @@ line. Good editors allow to do this with few keystrokes (ctrl-v on Vim).
|
||||
|
||||
def tricky_function():
|
||||
'''
|
||||
Commented out because its breaks something.
|
||||
if foo:
|
||||
do_bar()
|
||||
'''
|
||||
return baz
|
||||
|
||||
def tricky_function():
|
||||
# Commented out because its breaks something.
|
||||
#if foo:
|
||||
#do_bar()
|
||||
return baz
|
||||
|
||||
|
||||
def tricky_function():
|
||||
# Commented out because its breaks something.
|
||||
# if foo:
|
||||
# do_bar()
|
||||
return baz
|
||||
|
||||
**Good**
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def tricky_function():
|
||||
# Commented out because its breaks something.
|
||||
#if foo:
|
||||
# do_bar()
|
||||
return baz
|
||||
|
||||
|
||||
Note that comment text is properly written and separated from the hash by a
|
||||
space. Commented code is not separated from the hash by an additional space;
|
||||
this helps when uncommented the code.
|
||||
|
||||
The Basics
|
||||
::::::::::
|
||||
|
||||
@@ -172,6 +172,83 @@ Lastly, a convenient syntax is available for importing deeply nested packages:
|
||||
`import very.deep.module as mod` allow to use `mod` in place of the verbose
|
||||
repetition of `very.deep.module` in front of each calls to module items.
|
||||
|
||||
Object-oriented programming
|
||||
---------------------------
|
||||
|
||||
Python is sometime described as an object-oriented programming language. This
|
||||
can be somewhat misleading and need to be clarified.
|
||||
|
||||
In Python, everything is an object, and can be handled as such. This is what is
|
||||
meant when we say that, for example, functions are first-class objects.
|
||||
Functions, classes, strings, and even types are objects in Python: like any
|
||||
objects, they have a type, they can be passed as function arguments, they may
|
||||
have methods and properties. In this understanding, Python is an
|
||||
object-oriented language.
|
||||
|
||||
However, unlike Java, Python do not impose object-oriented programming as the
|
||||
main programming paradigm. It is perfectly viable for a Python project to not
|
||||
be object-oriented, ie. to use no or very few class definitions, class
|
||||
inheritance, and any other mechanism that are specific to object-oriented
|
||||
programming.
|
||||
|
||||
Moreover, as seen in the modules_ section, the way Python handles modules and
|
||||
namespaces gives directly to the developer a natural way to ensure
|
||||
encapsulation and separation of abstraction layers, both being the most common
|
||||
reasons to use object-orientation. Therefore, Python programmers have more
|
||||
latitude to not use object-orientation, when it is not required by the business
|
||||
model to be constructed.
|
||||
|
||||
There are some reasons to avoid unnecessary object-orientation. Definining
|
||||
custom classes is useful when we want to glue together some state and some
|
||||
functionality. The problem, as pointed out by the discussions about functional
|
||||
programming, comes from the "state" part of the equation.
|
||||
|
||||
In some architectures, typically web applications, instances of Python
|
||||
processes are spawned simultaneously to answer to external requests that can
|
||||
happen at the same time. In this case, holding some state into instanciated
|
||||
objects, which means keeping some static information about the world, is prone
|
||||
to concurrency problems or race-conditions: between the initialization of the
|
||||
state of an object, usually done with the __init__() method, and the actual use
|
||||
of the object state through one of its method, the world may have changed, and
|
||||
the retained state may be outdated. For example, a request may load an item in
|
||||
memory and mark it as read by a user. If another request requires the deletion
|
||||
of this item at the same, it may happen that the deletion actually occur after
|
||||
the first process loaded the item, and then we have to mark as read a deleted
|
||||
object.
|
||||
|
||||
This and other issues led to the idea that using stateless functions is a
|
||||
better programming paradigm.
|
||||
|
||||
Another way to say the same thing is to propose to use functions and procedures
|
||||
with as few implicit context and side-effects as possible. A function's
|
||||
implicit context is decelable when the function body refers to some global
|
||||
variables or fetches data from the persistence layer. Side-effects are the
|
||||
opposite: if a function body modifies the global context or save or delete data
|
||||
on the persistence layer, it is said to have side-effect.
|
||||
|
||||
Isolating carefully functions with context and side-effects from functions with
|
||||
logic (called pure functions) allow the following benefits:
|
||||
|
||||
- Pure functions are more likely to be deterministic: given a fixed input,
|
||||
the output will always be the same.
|
||||
|
||||
- Pure functions are much easier to change or replace if they need to
|
||||
be refactored or optimized.
|
||||
|
||||
- Pure functions are easier to test with unit-tests: There is less
|
||||
need for complex context setup and data cleaning afterwards.
|
||||
|
||||
- Pure functions are easier to manipulate, decorate_, pass-around.
|
||||
|
||||
In summary, pure functions, without any context or side-effects, are more
|
||||
efficient building blocks than classes and objects for some architectures.
|
||||
|
||||
Obviously, object-orientation is useful and even necessary in many cases, for
|
||||
example when developing graphical desktop applications or games, where the
|
||||
things that are manipulated (windows, buttons, avatars, vehicles) have a
|
||||
relatively long life of their own in the computer's memory.
|
||||
|
||||
|
||||
Vendorizing Dependencies
|
||||
------------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user