짧은 버전
mongo.MongoClient
는 것으로 보인다 객체를 반환 (입니까?) 당신이 다음 Storage
에 dbh
필드에 할당 추상적 인 방법. 이렇게하면 Storage
이 추상 클래스가되므로 인스턴스화하면 TypeError
이됩니다.
pymongo
이 없으므로 ABCMeta
으로 처리되는 것보다 MongoClient
에 대해 더 알려 드릴 수는 없습니다.
롱 버전
ABCMeta.__new__
방법은 만드는 것 새로운 클래스의 각 필드 내부 보인다. True
(또는 "true-like") __isabstractmethod__
필드가있는 필드는 모두 추상 메소드로 간주됩니다. 클래스에 이 있고 오버라이드되지 않은 추상 메소드가있는 경우 전체 클래스는 추상으로 간주되므로 인스턴스화하려는 모든 시도는 오류입니다. 이전 버전에서
표준 라이브러리의 abc.py
:이 abc.ABCMeta
클래스 문서에 언급되지 않은
def __new__(mcls, name, bases, namespace):
cls = super().__new__(mcls, name, bases, namespace)
# Compute set of abstract method names
abstracts = {name
for name, value in namespace.items()
if getattr(value, "__isabstractmethod__", False)}
# ...
cls.__abstractmethods__ = frozenset(abstracts)
# ...
하지만 @abc.abstractmethod
장식에 따라 약간 낮은 : 위해
에 추상 기본 클래스 기계와 정확하게 상호 작용하면, 설명자는 __isabstractmethod__
을 사용하여 자신을 추상으로 식별해야합니다. 기술자를 구성하는 데 사용 된 방법 중 하나라도 추상적 인 경우 일반적으로이 속성은 True
이어야합니다.
예 나는 __isabstractmethod__
속성 및 AbstractStorage
두 가정 콘크리트 서브 클래스와 가짜 "추상보고"클래스를 만들었습니다. 이 생산 실행
#!/usr/bin/env python3
import abc
# I don't have pymongo, so I have to fake it. See CounterfeitAbstractMethod.
#import pymongo as mongo
class CounterfeitAbstractMethod():
"""
This class appears to be an abstract method to the abc.ABCMeta.__new__
method.
Normally, finding an abstract method in a class's namespace means
that class is also abstract, so instantiating that class is an
error.
If a class derived from abc.ABCMeta has an instance of
CounterfeitAbstractMethod as a value anywhere in its namespace
dictionary, any attempt to instantiate that class will raise a
TypeError: Can't instantiate abstract class <classname> with
abstract method <fieldname>.
"""
__isabstractmethod__ = True
class AbstractStorage(metaclass=abc.ABCMeta):
def __init__(self):
"""
Do-nothing initializer that prints the name of the (sub)class
being initialized.
"""
print(self.__class__.__name__ + ".__init__ executing.")
return
class ConcreteStorage(AbstractStorage):
"""
A concrete class that also _appears_ concrete to abc.ABCMeta. This
class can be instantiated normally.
"""
whatever = "Anything that doesn't appear to be an abstract method will do."
class BogusStorage(AbstractStorage):
"""
This is (supposedly) a concrete class, but its whatever field appears
to be an abstract method, making this whole class abstract ---
abc.ABCMeta will refuse to construct any this class.
"""
#whatever = mongo.MongoClient('localhost', 27017)
whatever = CounterfeitAbstractMethod()
def main():
"""
Print details of the ConcreteStorage and BogusStorage classes.
"""
for cls in ConcreteStorage, BogusStorage:
print(cls.__name__ + ":")
print(" whatever field: " + str(cls.whatever))
print(" abstract methods: " + str(cls.__abstractmethods__))
print(" Instantiating...")
print(" ", end="")
# KABOOM! Instantiating BogusStorage will raise a TypeError,
# because it appears to be an _abstract_ class.
instance = cls()
print(" instance: " + str(instance))
print()
return
if "__main__" == __name__:
main()
:
$ ./storage.py
ConcreteStorage:
whatever field: Anything that doesn't appear to be an abstract method will do.
abstract methods: frozenset()
Instantiating...
ConcreteStorage.__init__ executing.
instance: <__main__.ConcreteStorage object at 0x253afd0>
BogusStorage:
whatever field: <__main__.CounterfeitAbstractMethod object at 0x253ad50>
abstract methods: frozenset({'whatever'})
Instantiating...
Traceback (most recent call last):
File "./storage.py", line 75, in <module>
main()
File "./storage.py", line 68, in main
instance = cls()
TypeError: Can't instantiate abstract class BogusStorage with abstract methods whatever
와우 당신은 하나가 정확한 오류 당신이 얻고을 만들어 볼 수 있습니다. 고마워 :) 아마도 mongo.version_tuple <(3, 0) : dbh .__ isabstractmethod__ = False'와 같은 것을 클래스 정의에서 작성해야합니다. – vaultah
@vaultah : 그렇게 할 수 있습니다. 그래도 상위 버전에서도 그 속성을 설정하는 것이 위험 할 것이라고 생각하지 않습니다. 그것은 조금 이상하게 보일 것입니다. – BrenBarn
실제 버그 보고서를 찾았습니다. (다른 뉴스에서는 생각했던 것보다 _way_을 더 느리게 입력했습니다.) –