Что такое python: чем он хорош, где пригодится и как его выучить
Содержание:
- Datatype mapping callbacks through DataHandler
- Event Properties
- Java 1.1
- API
- Calling Java Methods and Functions
- Overloaded Java Method Signatures
- Какие компании используют Python
- Using a JNDI lookup
- Major new features of the 3.8 series, compared to 3.7
- Examples from the Python standard library
- Java Classes Unloading
- Properties
- Example
- And now for something completely different
- 2.1.1. История создания¶
Datatype mapping callbacks through DataHandler
The DataHandler interface has three methods for handling type
mappings. They are called at two different times, one when fetching and
the other when binding objects for use in a prepared statement. I have
chosen this architecture for type binding because I noticed a number
of discrepancies in how different JDBC drivers handled database types,
in particular the additional types available in later JDBC versions.
- public void preExecute(Statement stmt) throws SQLException;
- A callback prior to each execution of the statement. If the statement
is a PreparedStatement (created when parameters are sent to the
execute method), all the parameters will have been set. - public void postExecute(Statement stmt) throws SQLException;
- A callback after successfully executing the statement. This is
particularly useful for cases such as auto-incrementing columns
where the statement knows the inserted value.
- public String getMetaDataName(String name);
- A callback for determining the proper case of a name used in a
DatabaseMetaData method, such as getTables(). This is particularly
useful for Oracle which expects all names to be upper case. - public PyObject getRowId(Statement stmt) throws SQLException;
- A callback for returning the row id of the last insert statement.
- public Object getJDBCObject(PyObject object, int type);
- This method is called when a PreparedStatement is created through
use of the execute method. When the parameters are being bound to
the statement, the DataHandler gets a callback to map the type. This
is only called if type bindings are present. - public Object getJDBCObject(PyObject object);
- This method is called when no type bindings are present during the
execution of a PreparedStatement.
- public PyObject getPyObject(ResultSet set, int col, int type);
- This method is called upon fetching data from the database. Given
the JDBC type, return the appropriate PyObject subclass from the
Java object at column col in the ResultSet set.
Event Properties
In standard Java, the event handlers for a widget are specified by passing in an instance of a class that implements the appropriate interface. This is the only reasonable approach to take in a language that doesn’t have first-class functions. In Jython, for every event listener supported by a class, there will be a property added to the class for each method supplied by the event listener class. These properties can be set to give a function to be called when the appropriate event occurs.
The standard Java style for setting an event listener is shown below:
class action(awt.event.ActionListener): def actionPerformed(self,event): java.lang.System.exit(0) button = awt.Button("Close Me!") button.addActionListener(action())
This can be written in a more Pythonesque (and compact) style by using event properties as follows:
Java 1.1
To be honest the unloading support that jython can offer under java
1.1 (given the absence of weak/soft-refs) is error-prone and anything
serious would require «too much» caution, but this should not be a real
issue. Support is offered only for «jreload» needs, in these forms:
# Before reload(X) one can issue X.unload(). X.unload() discards all the
entries for the old versions of the classes in X. This is safe only if
all python subclasses and all instances of them have been destroyed.
# One can «extract» the information needed in order to discard the
entries for the versions actually present in X at a later point (after
a whole series of reloads):
u_t1() is safe only if at that point all subclasses/instances of the
involved versions have been destroyed.
API
dbexts will default to looking for a file named ‘dbexts.ini’ in the same
directory as dbexts.py but can optionally be passed a filename to the
cfg attribute.
__init__(self, dbname=None, cfg=None, resultformatter=format_resultset, autocommit=1) The initialization method for the dbexts class. If dbname is None, the default connection, as specified in the cfg file will be used. isql(self, sql, params=None, bindings=None, maxrows=None) Interactively execute sql statement. If self.verbose is true, then the results (if any) are displayed using the result formatting method. If maxrows is specified, only maxrows are displayed. raw(self, sql, params=None, bindings=None, delim=None, comments=comments) Executes the sql statement with params and bindings as necessary. Returns a tuple consisting of (headers, results). schema(table, full=0, sort=1) Displays the schema (indicies, foreign keys, primary keys and columns) for the table parameter. If full is true, also compute the exported (or referenced) keys. If sort is true (the default), sort the column names. >>> d.schema("store") Table store Primary Keys store_id {store_3} Imported (Foreign) Keys location (city.city_id) {store_7} Exported (Referenced) Keys store_id (site_store.store_id) {site_store_8} Columns location int(4), non-nullable store_id serial(4), non-nullable store_name varchar(32), non-nullable Indices unique index {523_8115} on (store_id) unique index {store_ix_1} on (store_name) >>> table(table=None, types=("TABLE",), owner=None, schema=None) If no table argument, displays a list of all tables. If a table argument, displays the columns of the given table. proc(self, proc=None, owner=None, schema=None) If no proc argument, displays a list of all procedures. If a proc argument, displays the parameters of the given procedure. bcp(src, table, where='(1=1)', parameters=[], selective=[], ignorelist=[], autobatch=0) Bulk Copy from one database/table to another. The current instance of dbexts is the source database to which the results of the query on the foreign database will be inserted. An optional where clause can narrow the number of rows to be copied.
The following are generally not called since isql and raw can handle
almost all cases.
Calling Java Methods and Functions
Java classes have both static and instance methods this makes them
behave much like a cross between a Python module and class. As a user,
you should rarely need to be concerned with this difference.
Java methods and functions are called just exactly like their Python
counterparts. There is some automatic type coercion that goes on both for
the types being passed in and for the value returned by the method. The
following table shows how Python objects are coerced to Java objects
when passed as arguments in a function call. The Java Types show the
expected Java type for the argument, and the Allowed Python Types shows
what Python objects can be converted to the given Java type. Notice the
special behavior of String’s when a java.lang.Object is expected. This
behavior might change if it is shown to cause problems.
Java Types | Allowed Python Types |
---|---|
char | String (must have length 1) |
boolean | Integer (true = nonzero) |
byte, short, int, long | Integer |
float, double | Float |
java.lang.String, byte[], char[] | String |
java.lang.Class Class or JavaClass |
(only if class subclasses from exactly one Java class; mutiple inheritance from more than one Java class is now illegal) |
Foo[] | Array (must contain objects of class or subclass of Foo) |
java.lang.Object | String->java.lang.String, all others unchanged |
org.python.core.PyObject | All unchanged |
Foo | Instance->Foo (if Instance is subclass of Foo); JavaInstance -> Foo (if JavaInstance is instance of Foo or subclass) |
Returned values from a Java method are also possibly coerced back to an
object that is more readily usable in Python. The following table shows
those coercions.
Overloaded Java Method Signatures
Java methods are allowed to be overloaded for different signatures (types
and number of arguments). When different versions of the method differ
in the number of arguments that they expect, the appropriate method can
be easily determined from the number of arguments passed to the method.
When the difference is instead in the types of the arguments, more
work is required. The possible signatures are sorted in a consistent
order that should ensure the appropriate method is chosen first. TBD:
document this order!
If you need to call a Java method with a particular signature and this
is not happening in the easy way, you can use the following workaround:
Assume that foo has two methods, «void foo(int x); void foo(byte x);». To
call the second method you could write the following:
from java.lang import Byte foo(Byte(10))
I’m not convinced that any better solution to this problem is possible.
Какие компании используют Python
В основном Python используется стартапами и компаниями, которые разрабатывают крупные проекты. Вот лишь часть огромного списка:
- Alphabet использует язык для скраппинга в поисковике Google и реализации сервиса YouTube;
- One Laptop Per Child — для разработки интерфейса и модели функционирования;
- BitTorrent — для реализации сетей peer-to-peer;
- Агентство национальной безопасности США — для шифрования и анализа разведданных;
- ESRI — как инструмент настройки геоинформационных программ;
- Maya — для создания мультипликации;
- Pixar, Industrial Light & Magic — для создания анимационных фильмов;
- Intel, Cisco, HP, Seagate, Qualcomm и IBM — для тестирования;
- JPMorgan Chase, UBS, Getco и Citadel — для прогнозирования финансового рынка;
- NASA, Los Alamos, Fermilab, JPL — для научных вычислений;
- iRobot — для разработки коммерческих роботизированных устройств;
- IronPort — для реализации почтового сервера.
Using a JNDI lookup
It is possible for zxJDBC to use a Connection found through a JNDI
lookup. This is particularly useful in an application server (such as when
using PyServlet). The bound object can be either a String, Connection,
DataSource or ConnectionPooledDataSource. The lookup will figure out
the instance type and access the Connection accordingly,
The only required argument is the JNDI lookup name. All keyword arguments
will be converted to their proper Context field value if the keyword
matches one of the constants. If a field name does not exist for the
keyword, it will passed as declared. The resulting environment will be
used to build the InitialContext.
This example uses the simple Sun FileSystem JNDI reference
implementation. Please consult the JNDI implementation you intend to use
for the InitialContextFactory classname as well as the connection URL.
Major new features of the 3.8 series, compared to 3.7
- PEP 572, Assignment expressions
- PEP 570, Positional-only arguments
- PEP 587, Python Initialization Configuration (improved embedding)
- PEP 590, Vectorcall: a fast calling protocol for CPython
- PEP 578, Runtime audit hooks
- PEP 574, Pickle protocol 5 with out-of-band data
- Typing-related: PEP 591 (Final qualifier), PEP 586 (Literal types), and PEP 589 (TypedDict)
- Parallel filesystem cache for compiled bytecode
- Debug builds share ABI as release builds
- f-strings support a handy specifier for debugging
- is now legal in blocks
- on Windows, the default event loop is now
- on macOS, the spawn start method is now used by default in
- can now use shared memory segments to avoid pickling costs between processes
- is merged back to CPython
- is now 40% faster
- now uses Protocol 4 by default, improving performance
There are many other interesting changes, please consult the «What’s New» page in the documentation for a full list.
Examples from the Python standard library
env_base is only used on these lines, putting its assignment on the if
moves it as the «header» of the block.
-
Current:
env_base = os.environ.get("PYTHONUSERBASE", None) if env_base: return env_base
-
Improved:
if env_base := os.environ.get("PYTHONUSERBASE", None): return env_base
Avoid nested if and remove one indentation level.
-
Current:
if self._is_special: ans = self._check_nans(context=context) if ans: return ans
-
Improved:
if self._is_special and (ans := self._check_nans(context=context)): return ans
Code looks more regular and avoid multiple nested if.
(See Appendix A for the origin of this example.)
-
Current:
reductor = dispatch_table.get(cls) if reductor: rv = reductor(x) else: reductor = getattr(x, "__reduce_ex__", None) if reductor: rv = reductor(4) else: reductor = getattr(x, "__reduce__", None) if reductor: rv = reductor() else: raise Error( "un(deep)copyable object of type %s" % cls)
-
Improved:
if reductor := dispatch_table.get(cls): rv = reductor(x) elif reductor := getattr(x, "__reduce_ex__", None): rv = reductor(4) elif reductor := getattr(x, "__reduce__", None): rv = reductor() else: raise Error("un(deep)copyable object of type %s" % cls)
tz is only used for s += tz, moving its assignment inside the if
helps to show its scope.
-
Current:
s = _format_time(self._hour, self._minute, self._second, self._microsecond, timespec) tz = self._tzstr() if tz: s += tz return s
-
Improved:
s = _format_time(self._hour, self._minute, self._second, self._microsecond, timespec) if tz := self._tzstr(): s += tz return s
Java Classes Unloading
One would expect that no longer referenced java classes would be unloaded,
but the situation is not that simple.
In order to give a python-class-like view on python side and for
implementation reasons jython wraps java classes (in instances of
org.python.core.PyJavaClass). Clearly the mapping from java classes to
their wrapped version should be unique (e.g. to guarantee == and ‘is’
semantic). So jython keeps this mapping in an internal table. This is
also good because building the wrappers is expensive.
Note: Typically one should care about java classes unloading only for
very dynamic applications, like IDEs or long-running apps, that would
go out memory if old versions of reloaded classes would not be collected.
Clearly the entries somehow block unloading. On the other hand java
classes unloading is just a memory consumption optimization (and as such
is it presented in Java Language Specification). Actual jvms clearly
support this. JPython simply kept the entries in the table forever but
Jython and «jreload» try to make unloading possible.
Note: java never unloads system classes (java.* etc) nor classes from
classpath. Further Jython cannot unload sys.path java classes. So
the whole unload issue makes sense only with «jreload» or custom
class-loaders.
Java 2 and jython internalTablesImpl option
Under java2 jython offers table implementations that exploit soft/weak
references in order to discard entries (when this is OK) for unloading.
A possible policy would be to keep an entry as long as the corresponding
java class is still referenced outside the table (both by java or jython
code). But this one cannot be implemented. So entries are kept as long as
the wrapped version is still in use.
These implementations can be chosen trough
python.options.internalTablesImpl registry option. Note: they only
influence classes unloading, there is no need and reason to use them,
unless one depends on class unloading to avoid memory leakage.
internalTablesImpl = weak — Sets implementation using weak-refs. Table
entries for not referenced (outside the table) wrapped versions are
«discarded» at garbage collection points. If a class or some of its
instances are continuously passed from java to jython side, but no
long-living reference to it is kept from jython side, this can imply a
performance penalty (rebuilding the wrapped version is expensive). On
the other hand this is a good setting for testing if unloading actually
happens or some references hunting around prevent it.
Properties
Jython uses JavaBean properties to make it easier to interact with most Java classes. These properties can be used as normal object attributes, and can also be specified to the class constructor as keyword arguments (this idea is stolen from TkInter where it seems to work extremely well).
These properties are generated automatically using the JavaBean Introspector which identifies properties either from common design patterns, or from explicitly specified BeanInfo.
As a first example, consider the case where you wish to create a button that is disabled.
The first example shows how you would do this in the typical Java fashion:
b = awt.Button() b.setEnabled(0)
The second example shows how enabled can be set as a property:
b = awt.Button() b.enabled = 0
The final example sets this property at instantiation time using a keyword argument:
Example
The following example should help make things clearer: (its files should
be present in the jython Demo dir)
# Demo/jreload/example.jar contains example.Version (source) and
example.PrintVer (source)
# Demo/jreload/_xample contains a slightly modified version of
example.Version (source)
>>> import sys >>> import os >>> import jreload >>> def xp(name): return os.path.join(sys.prefix,'Demo/jreload/'+name) # builds a path under 'Demo/jreload' ... >>> X=jreload.makeLoadSet('X',) >>> from X import example >>> dir(example) >>> X.example.Version <jclass example.Version at 6781345> >>> from X.example import * # works but in general import * from java pkgs is not for production code >>> v=Version(1) >>> PrintVer.print(v) version 1 >>> os.rename(xp('_xample'),xp('example')) # _xample becomes example, hiding and "patching" jar contents >>> jreload.reload(X) # (re)loads example dir example.Version and jar example.PrintVer <java load-set X> >>> nv2=example.Version(2) >>> example.PrintVer.print(nv2) new version 2 >>> PrintVer.print(nv2) Traceback (innermost last): File "<console>", line 1, in ? TypeError: print(): 1st arg can't be coerced to example.Version >>> example.PrintVer.print(v) Traceback (innermost last): File "<console>", line 1, in ? TypeError: print(): 1st arg can't be coerced to example.Version >>> os.rename(xp('example'),xp('_xample'))
Note
Differently from python packages reload, load-sets reload the
complete hosted hierarchy.
Note
Class versions across reloads are not interoperable.
And now for something completely different
>
Graham Chapman: I think all rightthinking people in this country are sick and tired of being told that ordinary, decent people are fed up in this country with being sick and tired.
All: Yes, yes…
Graham Chapman: I’m certainly not! And I’m sick and tired of being told that I am.
Mrs. Havoc-Jones: Well, I meet a lot of people and I’m convinced that the vast majority of wrongthinking people are right.
Eric Idle: That seems like a consensus there.
Version | Operating System | Description | MD5 Sum | File Size | GPG |
---|---|---|---|---|---|
Gzipped source tarball | Source release | 4388c20bb59248a52adcaec7ce4a581c | 24063850 | SIG | |
XZ compressed source tarball | Source release | 5997ad4840d00bd6321e5102f0bae008 | 17902996 | SIG | |
macOS 64-bit installer | Mac OS X | for OS X 10.9 and later | fe18361ebdcf2a738679b189ac83e51d | 30114709 | SIG |
Windows help file | Windows | dade3016b80bb8b5928ee227f7415fc2 | 8572090 | SIG | |
Windows x86-64 embeddable zip file | Windows | for AMD64/EM64T/x64 | 17f75fd6cd5b554ff478d923b22a0f87 | 8176510 | SIG |
Windows x86-64 executable installer | Windows | for AMD64/EM64T/x64 | 17069c3a06cd44663d23d95d820f65e1 | 27812576 | SIG |
Windows x86-64 web-based installer | Windows | for AMD64/EM64T/x64 | 168644bb1d570bda4bac81a8d0d5ea13 | 1364128 | SIG |
Windows x86 embeddable zip file | Windows | b86b739d84c2d4eba2ceaff57e074afd | 7330372 | SIG | |
Windows x86 executable installer | Windows | b674fb697db9394fcf7bd39ab17ed024 | 26745552 | SIG | |
Windows x86 web-based installer | Windows | d4b1f174d4a769500bbd21710bba6cb0 | 1326272 | SIG |
2.1.1. История создания¶
Разработка языка Python была начата в конце 1980-х годов сотрудником голландского института CWI (Центр математики и информатики, голл. Centrum Wiskunde & Informatica) Гвидо ван Россумом (англ. Guido van Rossum), на основе языка ABC (Рисунок 2.1.1). В феврале 1991 года Гвидо опубликовал исходный текст в группе новостей alt.sources.
Рисунок 2.1.1 — Гвидо ван Россум на конференции в 2006 г.
О создании Python Гвидо ван Россум написал в 1996 г.:
В настоящее время Гвидо работает в компании Dropbox, покинув в декабре 2012 года корпорацию Google (2005-2012). Имея статус «великодушного пожизненного диктатора» проекта — он продолжает наблюдать за процессом разработки Python, принимая окончательные решения, когда это необходимо (не менее 50% рабочего времени по договоренности с DropBox).
Появившись сравнительно поздно, Python создавался под влиянием множества языков программирования. Так, например, влияние оказали такие языки, как:
-
ABC: отступы для группировки операторов, высокоуровневые структуры данных;
-
Modula-3: пакеты, модули;
-
С, C++: некоторые синтаксические конструкции;
-
Smalltalk: ООП;
-
Java: обработка исключений и др.
Большая часть других особенностей Python (например, байт-компиляция исходного кода) также была реализована ранее в других языках.
Развитие языка происходит согласно четко регламентированному процессу создания, обсуждения, отбора и реализации документов (Python Enhancement Proposal) — предложений по развитию Python.
В 2008 году, после длительного тестирования, вышла первая версия Python 3000 (или Python 3.0, также используется сокращение Py3k). В Python 3000 устранены многие недостатки архитектуры с максимально возможным (но не полным) сохранением совместимости со старыми версиями Python. На сегодня поддерживаются обе ветви развития (Python 3.x и 2.x) (сравнение и рекомендации), однако получать новый функционал будет только версия 3 .
Ключевые вехи развития языка приведены в Таблице 2.1.1.
Ветвь (дата выхода) |
Актуальная версия (дата выхода) (могла устареть) |
---|---|
Python 0.9.0 (1991-02) |
— |
Python 0.9.0 (1991-02) |
— |
Python 2.x (2000-10-16) |
Python 2.7.11 (2015-12-05) |
Python 3.x (2008-12-03) |
Python 3.4.5 (2016-06-27) |
Python 3.5.2 (2016-06-27) |
|
Python 3.6.1 (2017-03-21) |
На Видео 2.1.1 и 2.1.2 автор языка рассказывает об истории создания и развития Python (англ.).
Видео 2.1.1 — Guido van Rossum: The Early Years of Python