问题
We can import Container
in two ways:
from collections import Container
from collections.abc import Container
help
function for both Container
returns the same documentation.
help(collections.Container)
:
Help on class Container in module collections.abc:
class Container(builtins.object)
| Methods defined here:
|
| __contains__(self, x)
|
| ----------------------------------------------------------------------
| Class methods defined here:
|
| __subclasshook__(C) from abc.ABCMeta
| Abstract classes can override this to customize issubclass().
|
| This is invoked early on by abc.ABCMeta.__subclasscheck__().
| It should return True, False or NotImplemented. If it returns
| NotImplemented, the normal algorithm is used. Otherwise, it
| overrides the normal algorithm (and the outcome is cached).
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| __abstractmethods__ = frozenset({'__contains__'})
help(collections.abc.Container)
:
Help on class Container in module collections.abc:
class Container(builtins.object)
| Methods defined here:
|
| __contains__(self, x)
|
| ----------------------------------------------------------------------
| Class methods defined here:
|
| __subclasshook__(C) from abc.ABCMeta
| Abstract classes can override this to customize issubclass().
|
| This is invoked early on by abc.ABCMeta.__subclasscheck__().
| It should return True, False or NotImplemented. If it returns
| NotImplemented, the normal algorithm is used. Otherwise, it
| overrides the normal algorithm (and the outcome is cached).
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| __abstractmethods__ = frozenset({'__contains__'})
What is the difference between these two imports? Why are we allowed to do both?
Update
Got deprecation warning while importing Container
from collections
(Python 3.7.3
).
From Python 3.8
it cannot be imported directly from collections
.
>>> from collections import Container
main:1: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
回答1:
From the Python 3 documentation for the collections module:
Changed in version 3.3: Moved Collections Abstract Base Classes to the collections.abc module. For backwards compatibility, they continue to be visible in this module through Python 3.7. Subsequently, they will be removed entirely.
These "Collections Abstract Base Classes" currently include
AsyncGenerator
, AsyncIterable
, AsyncIterator
, Awaitable
,
Bytestring
, Callable
, Collection
, Container
, Coroutine
,
Generator
, Hashable
, ItemsView
, Iterable
, Iterator
, KeysView
,
Mapping
, MappingView
, MutableMapping
, MutableSequence
,
MutableSet
, Reversible
, Sequence
, Set
, Sized
, ValuesView
.
In Python 3.8 importing them from collections
will stop working.
In Python 3.3 to 3.7, they can be imported from collections
or
from collections.abc
(it gives the exact same classes).
In Python 3.7, importing them from collections
prints a
deprecation warning, since Python 3.8 is getting near.
In Python 2 they can only be imported from 'collections', not from 'collections.abc'.
One simple way to deal with this is a try/except block:
try: # works in Python >= 3.3
from collections.abc import Sequence
except ImportError: # Python 2, Python <= 3.2
from collections import Sequence
Another commonly used workaround is to conditionally
import from collections
or collections.abc
depending
on the Python version being used.
For instance, have a PY2
boolean and do:
if PY2:
from collections import Sequence
else:
from collections.abc import Sequence
This boolean is usually obtained either using six
:
from six import PY2
or using sys.version_info
:
import sys
PY2 = int(sys.version_info[0]) == 2
If we anticipate that Python 4 is likely to work like Python 3.3+ in this respect, special-casing Python 2 seems more future-proof than special-casing Python 3, which could be done as follows:
if PY3:
from collections.abc import Sequence
else:
from collections import Sequence
where the PY3
boolean can be obtained either using six
:
from six import PY3
or using sys.version_info
:
import sys
PY3 = int(sys.version_info[0]) == 3
The try/except approach above seems even more robust though (e.g. it works with Python 3.2 with no extra effort).
来源:https://stackoverflow.com/questions/55882715/difference-between-from-collections-import-container-and-from-collections-abc-im