天道酬勤,学无止境

When inheriting SQLAlchemy class from abstract class exception thrown: metaclass conflict: the metaclass of a derived class must be

The following code is a very simple implementation of a SqlAlchemy ORM with one simple table. The Mytable class tries to inherit from BaseAbstract.

The code throws the following exception:

Message: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

from abc import ABC
from sqlalchemy import Column, Integer, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

class BaseAbstract(ABC):
    """description of class"""

SQLALCHEMY_DATABASE_URI =\
   'mssql+pyodbc://(local)/TestDB?driver=SQL+Server+Native+Client+11.0'
SQLALCHEMY_TRACK_MODIFICATIONS = False

engine = create_engine(SQLALCHEMY_DATABASE_URI, echo=True)
Session = sessionmaker(bind=engine)
session = Session()

Base = declarative_base()
metadata = Base.metadata

class Mytable(Base, BaseAbstract):
    __tablename__ = 'myTable'

    id = Column(Integer, primary_key=True)
    firstNum = Column(Integer, nullable=False)
    secondNum = Column(Integer, nullable=False)

If you change the class declaration line to

class Mytable(Base):

the code will work fine. Also if you change class BaseAbstract(ABC): to class BaseAbstract(object): the code will again work fine. How do I inherit from an abstract class in SQLAlchemy?

评论

Mixing metaclasses is not easy and you should avoid it. SQLAlchemy offers a way to handle abstract base classes or augmenting the base, and on the other hand what you're trying to do looks a lot like a mixin.

You can instruct SQLAlchemy to skip creating a table and a mapper for a class using __abstract__:

Base = declarative_base()

class BaseAbstract(Base):
    """description of class"""
    __abstract__ = True

class Mytable(BaseAbstract):
    ...

You could also augment the Base class:

class BaseAbstract:
    """description of class"""

Base = declarative_base(cls=BaseAbstract)

class Mytable(Base):
    ...

But in my opinion the easiest solution is to forego using an "abstract base" altogether and think of it as a mixin, as you had done already in a way:

class CommonMixin:
    """description of class"""

Base = declarative_base()

class Mytable(CommonMixin, Base):
    ...

But if you insist on using an actual abc.ABC abstract base class, register your model classes as virtual subclasses:

class BaseAbstract(ABC):
    """description of class"""

Base = declarative_base()

@BaseAbstract.register
class Mytable(Base):
    ...

The downside is that @abc.abstractmethod decorated methods are not checked upon instantiating virtual subclasses.

If the above do not fulfill your needs and you want to use ABC for checking that required methods are implemented, you could try and do as the exception instructed and create a new metaclass that is the combination of DeclarativeMeta and ABCMeta:

In [6]: class DeclarativeABCMeta(DeclarativeMeta, abc.ABCMeta):
   ...:     pass
   ...: 

In [7]: Base = declarative_base(metaclass=DeclarativeABCMeta)

In [8]: class BaseAbstract(abc.ABC):
   ...:     @abc.abstractmethod
   ...:     def foo(self):
   ...:         pass
   ...:     

In [13]: class MyTable(Base, BaseAbstract):
    ...:     __tablename__ = 'mytable'
    ...:     id = Column(Integer, primary_key=True)
    ...:     

In [14]: MyTable()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-14-1686a36a17c6> in <module>()
----> 1 MyTable()

TypeError: "Can't instantiate abstract class MyTable with abstract methods foo"

In [18]: class MyOtherTable(Base, BaseAbstract):
    ...:     __tablename__ = 'myothertable'
    ...:     id = Column(Integer, primary_key=True)
    ...:     def foo(self):
    ...:         return 'bar'
    ...:     

In [19]: MyOtherTable()
Out[19]: <__main__.MyOtherTable at 0x7f01b4b592b0>

I cannot vouch for this, though. It might contain more than a few surprises.

I came across the same problem. In addition to the very good answer of Ilja and just because in a comment on their answer you are asking

The reason I am trying to inherit from an abstract class inheriting from ABC is to use isinstance in a function that takes as an argument an object and if that returns true then do additional processing by calling methods defined in the abstract class. If I do not inherit from ABC, Python will not enforce my need to make sure the inherited class implements all the attributes of the abstract class, and if I have missed some in an implementation, then I will get a run-time exception. I would rather get a build exception. That is what ABC gives me. Is this not a good reason to use ABC?

I would like to share the workaround I created before I came here. Besides ABC, Python provides another way to check for the presence of a certain method during class instantiation, i.e. in the __init_subclass__ magic method. I did the following:

class BaseAbstract:
    ABSTRACT_METHODS = [
        "some_method", "another_method"
    ]

    def __init_subclass__(cls):
        for method_name in BaseAbstract.ABSTRACT_METHODS:
            method = getattr(cls, method_name, None)
            if not method or not callable(method):
                raise TypeError(
                    f"Can't instantiate abstract class {cls.__name__} with "
                    f"abstract methods {method_name}."
                )

Using inspect, you could also check for constraints on the signatures of the "abstract" methods.

It is a matter of argument whether this is the better way to go than using one of Ilja's ideas. I just want to share my approach, not claiming that it was superior.

I see two neat characteristics of my workaround:

  1. I have only one SQLalchemy Base. So I don't have to worry about mutiple Bases, for instance when using alembic's feature to autogenerate migrations or when calling Base.metadata.create_all()

  2. I do not actually have to understand what the problem was. If you have never dealt with metadata conflicts, with my approach is easier to understand why it fixes the problem.

But still, it could be considered some sort of hacky. It also has the characteristic of checking for method presence during class initialization, not during instantiation. This is a limitation, in case you have cascading inheritances, where all the methods are present on the last child, but not on all intermediate classes in the inheritance chain.

You should be able to solve the issue by introducing an intermediate base class for your Mytable. For example:

Base = declarative_base()
metadata = Base.metadata

class IntermediateBase(type(Base), BaseAbstract):
    pass

class Mytable(IntermediateBase):
    __tablename__ = 'myTable'

    id = Column(Integer, primary_key=True)
    firstNum = Column(Integer, nullable=False)
    secondNum = Column(Integer, nullable=False)

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • SQLAlchemy:从表名称获取模型。 据我所知,这可能暗示将某些函数附加到元类构造函数中(SQLAlchemy: get Model from table name. This may imply appending some function to a metaclass constructor as far as I can see)
    问题 我想做一个函数,给定一个表的名称,返回具有该表名的模型。 例如: class Model(Base): __tablename__ = 'table' ...a bunch of Columns def getModelFromTableName(tablename): ...something magical 因此getModelFromTableName('table')应该返回Model类。 我的目标是在我制作的简单表单生成器中使用该函数,因为FormAlchemy不适用于python3.2,并且我希望它能很好地处理外键。 谁能给我有关如何使getModelFromTableName工作的任何指示? 这是我的一个想法(可能是完全错误的,之前我没有使用过元类...) 如果我要让我的Model类继承自Base以及其他一些类(TableReg),并让TableReg的类元存储Model,该怎么办? 表名在某些全局字典或辛格尔顿。 我意识到这可能完全不可行,因为Base的元类做了一些我不想破坏的非常重要且非常漂亮的事情,但是我认为必须有一种方法可以向元类添加一些构造函数代码我的模型。 否则我不明白。 回答1 受伊芙评论的启发: def get_class_by_tablename(tablename): """Return class reference mapped to
  • SqlAlchemy 元类混淆(SqlAlchemy metaclass confusion)
    问题 我试图在SqlAlchemy的类构建过程中注入一些我自己的代码。 试图理解代码,我对元类的实现有些困惑。 以下是相关的片段: SqlAlchemy 的默认“元类”: class DeclarativeMeta(type): def __init__(cls, classname, bases, dict_): if '_decl_class_registry' in cls.__dict__: return type.__init__(cls, classname, bases, dict_) else: _as_declarative(cls, classname, cls.__dict__) return type.__init__(cls, classname, bases, dict_) def __setattr__(cls, key, value): _add_attribute(cls, key, value) declarative_base是这样实现的: def declarative_base(bind=None, metadata=None, mapper=None, cls=object, name='Base', constructor=_declarative_constructor, class_registry=None, metaclass
  • 在所有继承类中强制实现一个方法(Force implementation of a method in all inheriting classes)
    问题 我有一种情况,我想强制从某个(抽象)类继承的每个类来实现一个方法。 这是我通常会使用@abstractmethod 实现的目标。 但是,考虑到这种多重继承的情况: from abc import ABCMeta, abstractmethod class A(object): __metaclass__ = ABCMeta @abstractmethod def very_specific_method(self): pass class B(A): def very_specific_method(self): print 'doing something in B' class C(B): pass 我也想强制C来实现该方法。 我希望每个直接或间接继承 A 的类都被强制实现该方法。 这可能吗? 澄清:我希望这适用于特定方法,而不是所有抽象方法。 抽象方法应该继续以相同的方式工作,但也许应该创建一个新的装饰器来指示不同类型的方法。 旁注:我在问题中使用了 abc,因为这似乎与该问题最相关。 我了解抽象方法通常如何工作并定期使用它们。 这是一种不同的情况,我不介意不是通过 abc 完成的。 回答1 ABCMeta 的修改版本应该可以解决问题。 在这里,不是只在基类中检查__isabstractmethod__设置为True方法,我们可以检查它是否在类的 MRO 中,如果它在
  • SQLAlchemy: get Model from table name. This may imply appending some function to a metaclass constructor as far as I can see
    I want to make a function that, given the name of a table, returns the model with that tablename. Eg: class Model(Base): __tablename__ = 'table' ...a bunch of Columns def getModelFromTableName(tablename): ...something magical so getModelFromTableName('table') should return the Model class. My aim is to use the function in a simple form generator I'm making since FormAlchemy does not work with python3.2 and I want it to handle foreign keys nicely. Can anyone give me any pointers on how to get getModelFromTableName to work? Here's one idea I have (it might be totally wrong, I haven't worked with
  • 强制子类在重写时调用父方法(Force child class to call parent method when overriding it)
    问题 我很好奇Python中是否有一种方法(从Parent类中)强制要在子类被重写时从子类中调用父方法。 例子: class Parent(object): def __init__(self): self.someValue=1 def start(self): ''' Force method to be called''' self.someValue+=1 我希望我的孩子Child班做的正确实现是: class ChildCorrect(Parent): def start(self): Parent.start(self) self.someValue+=1 但是,有一种方法可以迫使开发Child类的开发人员专门调用(而不是覆盖)在Parent类中定义的“ start”方法,以防万一他们忘记调用它: class ChildIncorrect(Parent): def start(self): '''Parent method not called, but correctly overridden''' self.someValue+=1 另外,如果这不是最佳做法,那有什么替代方法? 回答1 怎么做(不做) 不,没有安全的方法来强迫用户调用超级。 让我们讨论一些可以达到该目标或类似目标的选项,并讨论为什么这是一个坏主意。 在下一节中,我还将讨论处理这种情况的明智的方式
  • python入门教程09-04 (python语法入门之多态性与鸭子类型)
    多态指的是一类事物有多种形态,比如动物有多种形态:猫、狗、猪classAnimal: #同一类事物:动物 deftalk(self): passclassCat(Animal): #动物的形态之一:猫 deftalk(self): print(‘喵喵喵’)classDog(Animal): #动物的形态之二:狗 deftalk(self): print(‘汪汪汪’)classPig(Animal): #动物的形态之三:猪 deftalk(self): print(‘哼哼哼’)#实例化得到三个对象>>> cat=Cat()>>> dog=Dog()>>> pig=Pig()多态性指的是可以在不用考虑对象具体类型的情况下而直接使用对象,这就需要在设计时,把对象的使用方法统一成一种:例如cat、dog、pig都是动物,但凡是动物肯定有talk方法,于是我们可以不用考虑它们三者的具体是什么类型的动物,而直接使用cat.talk()喵喵喵>>> dog.talk()汪汪汪>>> pig.talk()哼哼哼更进一步,我们可以定义一个统一的接口来使用defTalk(animal):… animal.talk()… >>> Talk(cat)喵喵喵>>> Talk(dog)汪汪汪>>> Talk(pig)哼哼哼Python中一切皆对象,本身就支持多态性多态性的好处在于增强了程序的灵活性和可扩展性
  • 在Sqlalchemy中进行枚举的最佳方法?(Best way to do enum in Sqlalchemy?)
    问题 我正在阅读有关sqlalchemy的信息,并且看到了以下代码: employees_table = Table('employees', metadata, Column('employee_id', Integer, primary_key=True), Column('name', String(50)), Column('manager_data', String(50)), Column('engineer_info', String(50)), Column('type', String(20), nullable=False) ) employee_mapper = mapper(Employee, employees_table, \ polymorphic_on=employees_table.c.type, polymorphic_identity='employee') manager_mapper = mapper(Manager, inherits=employee_mapper, polymorphic_identity='manager') engineer_mapper = mapper(Engineer, inherits=employee_mapper, polymorphic_identity='engineer') 我应该在库中使用常量将
  • Python中抽象类和接口之间的区别(Difference between abstract class and interface in Python)
    问题 Python中的抽象类和接口有什么区别? 回答1 有时您会看到以下内容: class Abstract1: """Some description that tells you it's abstract, often listing the methods you're expected to supply.""" def aMethod(self): raise NotImplementedError("Should have implemented this") 由于Python没有(也不需要)正式的Interface契约,因此不存在抽象和接口之间的Java风格区别。 如果有人努力定义一个正式的接口,它也将是一个抽象类。 唯一的区别在于文档字符串中所述的意图。 当您进行鸭类输入时,抽象和接口之间的区别是令人不解的事情。 Java使用接口是因为它没有多重继承。 由于Python具有多重继承,因此您可能还会看到类似这样的内容 class SomeAbstraction: pass # lots of stuff - but missing something class Mixin1: def something(self): pass # one implementation class Mixin2: def something(self): pass #
  • 第三模块:面向对象&网络编程基础-第1章 面向对象
    系列文章目录 面向对象编程设计与开发 文章目录 系列文章目录前言一、面向过程编程二、面向对象编程1.面向对象编程介绍2.定义类与实例化出对象3.如何使用类4.如何使用对象5.属性查找与绑定方法6.python中一切皆对象7.面向对象可扩展性总结8.小练习19.小练习2 三、继承与重用性1.什么是继承2.派生3.继承的实现原理4.子类中调用父类的方法或属性5.组合6.抽象类与归一化 四、多态与多态性五、封装1.封装之如何隐藏属性2.封装的意义3.封装与可扩展性4.property的使用 六、绑定方法与非绑定方法1.绑定方法与非绑定方法介绍2.绑定方法与非绑定方法使用 七、反射八、内置方法九、元类1.元类介绍2.自定义元类控制类的创建3.自定义元类控制类的实例化行为4.自定义元类控制类的实例化行为的应用 十、面向对象软件开发十一、异常处理1.什么是异常处理2.try...except详细用法 总结 前言 面向对象编程设计与开发 一、面向过程编程 """面向过程:核心是过程二字,过程指的是解决问题的步骤,设计一条流水线,机械式的思维方式 优点:复杂问题流程化,进而简单化 缺点:可扩展性差 应用场景:面向过程的程序设计思想一般用于那些功能一旦实现之后就很少需要改变的场景 """ import json import re def interactive(): name = input(">
  • SQLAlchemy ORM __init__ 方法对比(SQLAlchemy ORM __init__ method vs)
    问题 在 SQLAlchemy ORM 教程中,给出了以下代码作为将映射到表的类的示例: >>> from sqlalchemy import Column, Integer, String >>> class User(Base): ... __tablename__ = 'users' ... ... id = Column(Integer, primary_key=True) ... name = Column(String) ... fullname = Column(String) ... password = Column(String) ... ... def __init__(self, name, fullname, password): ... self.name = name ... self.fullname = fullname ... self.password = password ... ... def __repr__(self): ... return "<User('%s','%s', '%s')>" % (self.name, self.fullname, self.password) 如果在实例化类时用户在__init__方法中设置了name 、 fullname和password ,那么将它们声明为Column对象(即作为类变量
  • 如何在Ruby中实现一个抽象类?(How to implement an abstract class in ruby?)
    问题 我知道红宝石中没有抽象类的概念。 但是,如果根本需要实施,该怎么做呢? 我尝试过类似... class A def self.new raise 'Doh! You are trying to write Java in Ruby!' end end class B < A ... ... end 但是,当我尝试实例化B时,它将在内部调用A.new ,这将引发异常。 同样,模块不能被实例化,但是它们也不能被继承。 将新方法设为私有也将不起作用。 有指针吗? 回答1 我不喜欢在Ruby中使用抽象类(几乎总是有更好的方法)。 如果您确实认为这是针对这种情况的最佳技术,则可以使用以下代码段来更明确地声明哪些方法是抽象的: module Abstract def abstract_methods(*args) args.each do |name| class_eval(<<-END, __FILE__, __LINE__) def #{name}(*args) raise NotImplementedError.new("You must implement #{name}.") end END # important that this END is capitalized, since it marks the end of <<-END end end end require
  • 在子类中强制类变量(Enforcing Class Variables in a Subclass)
    问题 我正在为App Engine扩展Python webapp2网络框架,以引入一些缺少的功能(以使创建应用程序更快更轻松)。 这里的要求之一是每个子类都需要具有一些特定的静态类变量。 是实现此目标的最佳方法,就是在我去使用它们时是否缺少它们,或者是否有更好的方法来简单地引发异常? 示例(非真实代码): 子类: class Bar(Foo): page_name = 'New Page' 必须存在page_name才能在此处进行处理: page_names = process_pages(list_of_pages) def process_pages(list_of_pages) page_names = [] for page in list_of_pages: page_names.append(page.page_name) return page_names 回答1 抽象基类允许声明一个属性抽象,这将强制所有实现类都具有该属性。 我仅出于完整性的目的提供此示例,许多pythonista人士认为您提出的解决方案更具pythonic的功能。 import abc class Base(object): __metaclass__ = abc.ABCMeta @abc.abstractproperty def value(self): return 'Should never
  • 抽象基类强制每个派生类为Singleton(Abstract base class to force each derived classes to be Singleton)
    问题 如何制作一个抽象类,将每个派生类强制为Singleton? 我使用C#。 回答1 当您要进行编译时检查时,这是不可能的。 通过运行时检查,您可以执行此操作。 这不漂亮,但是有可能。 这是一个例子: public abstract class Singleton { private static readonly object locker = new object(); private static HashSet<object> registeredTypes = new HashSet<object>(); protected Singleton() { lock (locker) { if (registeredTypes.Contains(this.GetType())) { throw new InvalidOperationException( "Only one instance can ever be registered."); } registeredTypes.Add(this.GetType()); } } } public class Repository : Singleton { public static readonly Repository Instance = new Repository(); private Repository()
  • 为什么从Base继承的SQLAlchemy类不需要构造函数?(Why do SQLAlchemy classes inheriting from Base not need a constructor?)
    问题 使用从Base类继承的SQLAlchemy对象,我可以将参数传递给未在构造函数中定义的变量的类: from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class User(Base): __tablename__ = 'users' id = Column(Integer, Sequence('user_id_seq'), primary_key=True) name = Column(String(50)) fullname = Column(String(50)) password = Column(String(12)) def __repr__(self): return "<User(name='%s', fullname='%s', password='%s')>" % ( self.name, self.fullname, self.password) ed_user = User(name='ed', fullname='Ed Jones', password='edspassword') 当然,如果我尝试将这样的参数传递给另一个类,则以与得到错误的相同方式设置类变量: In [1]: class MyClass(object): ...: i =
  • 入门语言JavaSE基础
    面向对象继承:继承是从已有的类中得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类,基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段。封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只是向外界提供最简单的编程接口。多态性:多态性是指允许不同子类类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供服务的方式,但一切对A系统来说都是透明的。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称后绑定)。运行时的多态时面向对象最精髓的东西,要实现多态需要做两件事:1.方法重写(子类继承父类并重写父类中已有的或抽象的方法);2.对象造型(用父类型的引用引用子类型对象,这样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。抽象:抽象是将一类对象的共同特征总结出来构造类的过程
  • 带有另一个基类的python abstractmethod破坏了抽象功能(python abstractmethod with another baseclass breaks abstract functionality)
    问题 考虑下面的代码示例 import abc class ABCtest(abc.ABC): @abc.abstractmethod def foo(self): raise RuntimeError("Abstract method was called, this should be impossible") class ABCtest_B(ABCtest): pass test = ABCtest_B() 这正确地引发了错误: Traceback (most recent call last): File "/.../test.py", line 10, in <module> test = ABCtest_B() TypeError: Can't instantiate abstract class ABCtest_B with abstract methods foo 但是,当ABCtest的子类也继承自诸如str或list之类的内置类型时,则没有错误,并且test.foo()调用了抽象方法: class ABCtest_C(ABCtest, str): pass >>> test = ABCtest_C() >>> test.foo() Traceback (most recent call last): File "<pyshell#0>", line 1, in
  • Python元类实战,动手实现数据库ORM框架
    今天是Python专题的第19篇文章,我们一起来用元类实现一个简易的ORM数据库框架。 本文主要是受到了廖雪峰老师Python3入门教程的启发,不过廖老师的博客有些精简,一些小白可能看起来比较吃力。我在他的基础上做了一些补充和注释,尽量写得浅显一些。 ORM框架是什么 如果是没有做过后端的小伙伴上来估计会有点蒙,这个ORM框架究竟是什么?ORM框架是后端工程师常用的一个框架,它的英文全称是Object Relational Mapping,即对象-关系映射框架。顾名思义就是把关系转化成对象的框架,关系这个词我们在哪里用的最多呢? 显然应该是数据库。之前我们在分布式的文章介绍关系型数据库和非关系型数据库的时候就着重介绍过关系的含义。我们常用的MySQL就是经典的关系型数据库,它存储的形式是表,但是表承载的数据其实是两个实体之间的"关系"。比如学生上课这个场景,学生和课程是两个主体(entity),我们要记录的是这两个主体之间的关系,也就是学生上课这件事。 而ORM框架做的事情是将这些关系映射成类,这样我们可以将这张表当中增删改查的功能抽象成类当中的方法。这样我们就可以通过调用类的方式来操作数据库了,从而达到高度抽象业务逻辑、降低用户使用难度的目的。 比如Java后端工程师常用的hibernate和ibatis都是用来做这件事情的,明确了框架的功能之后,我们先来设想一下最后的成果
  • python 如何定义抽象类和抽象方法
    文章目录 (一)python 如何定义抽象类和抽象方法(二)python中的多态(三)类的组合 (一)python 如何定义抽象类和抽象方法 在python中类 通过继承metaclass = ABCmeta类来创建抽象类,抽象类是包含抽象方法的类,其中ABCmeta类(Metaclass for defining abstact baseclasses,抽象基类的元类)是所有抽象类的基类。 定义了抽象类后,在要实现抽象方法的前一行使用@abc.abstractmethod来定义抽象方法。抽象方法不包含任何可实现的代码,只能在子类中实现抽象函数的代码。 抽象类的特点: 抽象类不能被实例化继承抽象类的类必须实现所有的抽象方法后,才能被实例化抽象类中有抽象方法和正常方法抽象类中可以添加成员属性 注意: 抽象类中的抽象方法,在子类中必须实现该方法 抽象类不能被实例化 创建抽象方法前,必须先创建抽象类 需要导入abc(abstractclass)类 python是动态语言(在程序运行时检查类型,对比:java是静态语言,在程序运行前检查类型)。动态语言调用实例方法,不检查类型,只要方法存在,参数正确,就可以调用 ; 也就是说,例如:传递给函数 who_am_i(x)的参数 x 不一定是 Person 或 Person 的子类型。任何数据类型的实例都可以,只要它有一个whoAmI()的方法
  • Django抽象模型vs简单Python mixins vs Python ABC(Django Abstract Models vs simple Python mixins vs Python ABCs)
    问题 这是我提出的另一个问题提示的一个问题。 Django提供了Abstract基类功能(与Python中的ABC类不同吗?),因此可以创建一个可以继承的模型(Django的models.Model),但是该模型在数据库中没有实际的表。 通过在模型的Meta类中设置“抽象”属性来触发此行为。 现在的问题是:为什么Django用这种方式解决它? 为什么需要这种特殊的“抽象基类”模型? 为什么不通过仅继承对象类并将其与现有Model混合来进行Model mixin? 还是可以通过Python ABC的任务来做到这一点? (请注意,我对Python中的ABC类不是很熟悉,我的无知可能显示在这里) 回答1 我会尽量简短些,因为这很容易变成冗长的异味: ABC之所以出现是因为它们仅在Python 2.6中引入,并且Django开发人员为Python版本支持制定了一套路线图(2.3支持仅在1.2中下降了)。 至于对象继承混合器,它们在Python方面的作用要比仅仅降低可读性的方式要少。 Django对Model对象使用ModelBase元类,它实际上在初始化时分析定义的模型属性,并使用字段, Meta选项和其他属性填充Model._meta 。 对于两种类型的模型都可以重用该框架。 这也允许Django防止继承模型来覆盖抽象模型字段。 我能想到的原因还有很多,它们全都是次要的
  • python面向对象--李继昂的技术博客
    Python面向对象 一、封装二、继承三、多态 pyhton面向对象特征总结 抽象是隐藏多余细节的艺术。在面向对象的概念中,抽象的直接表现形式通常为类。Python基本上提供了面向对象编程语言的所有元素,如果你已经至少掌握了一门面向对象语言,那么利用Python进行面向对象程序设计将会相当容易。 一、封装 面向对象程序设计中的术语对象(Object)基本上可以看做数据(特性)以及由一系列可以存取、操作这些数据的方法所组成的集合。传统意义上的“程序=数据结构+算法”被封装”掩盖“并简化为“程序=对象+消息”。对象是类的实例,类的抽象则需要经过封装。封装可以让调用者不用关心对象是如何构建的而直接进行使用。 一个简单的Python类封装如下: _metaclass_=type # 确定使用新式类 class Animal: def __init__(self): #构造方法 一个对象创建后会立即调用此方法 self.Name="Doraemon" print self.Name def accessibleMethod(self): #绑定方法 对外公开 print "I have a self! current name is:" print self.Name print "the secret message is:" self.__inaccessible() def _