from sqlalchemy import create_engine
from sqlalchemy import Sequence
Base = declarative_base()
Column(Integer, Sequence('user_id_seq'), primary_key=True)
engine = create_engine('sqlite:///:memory:', echo=True)
class User(Base):
__tablename__ = 'users'
id = Column(Integer, Sequence('user_id_seq'), primary_key=True)
name = Column(String(50))
fullname = Column(String(50))
nickname = Column(String(50))
def __repr__(self):
return "<User(name='%s', fullname='%s', nickname='%s')>" % (
self.name, self.fullname, self.nickname)
class User1(Base):
__tablename__ = 'users1'
id = Column(Integer, Sequence('user_id_seq'), primary_key=True)
name = Column(String(50))
fullname = Column(String(50))
nickname = Column(String(50))
def __init__(self, name, fullname, nickname):
self.name = name
self.fullname = fullname
self.nickname = nickname
def __repr__(self):
return "<User(name='%s', fullname='%s', nickname='%s')>" % (
self.name, self.fullname, self.nickname)
ed_user = User(name='ed', fullname='Ed Jones', nickname='edsnickname')
ed_user = User1(name='edd', fullname='Edd Jones', nickname='edsnick')
i picked up this piece of code from the sqlalchemy documentation website, I think everything is okay, but i have a problem understanding the last line, the class user inherits from the base class, buy the user class is not having an init methods in other to accept any argument. can some please explain this to me.. thanks. this two-class achieves the same result they create a table, but in the second instance, the User1 has an init method declared, so obviously the creation of the table happens in the base class, but in the second instance the class and instance variable were declared I want to know how will the base class be able to create the table if it is not receiving any data from the child class.
Python is a very dynamic language. There are several ways to achieve this. One is inheriting from its superclass, as @vrevolverr says. But unfortunately here is not this case. You can confirm that by running print(Base.__init__ is User.__init__)
, which will give you a False
. That means User.__init__
is not inherited from Base
.
Another evidence is that print('__init__' in User.__dict__)
gives you True
, which means that User
class has its own __init__
method. And this method can only be given by its metaclass. So the answer comes out. By the way, in your case, this metaclass is DeclarativeMeta
in sqlalchemy.ext.declarative
.
Just FYI. Simply put, metaclass can do something during the creating process of a class. For example, add a method to this class. This is where your __init__
comes from.
Update:
My original answer also solves your second question. But I still want to add some comments.
First, does User1.__init__
take effect? The answer is NO. Try this simple test:
def init(self, name, fullname, nickname):
self.name = name
self.fullname = fullname
self.nickname = nickname
class User(Base):
...
__init__ = init
print(User.__init__ is init) # False
You can see that the __init__
method defined by you is already replaced.
Then, how to perform this "magic"? See below:
def init1(self):
pass
def init2(self):
pass
class MyMeta(type):
# You can also do this in __new__
def __init__(cls, *args, **kwargs):
cls.__init__ = init2
type.__init__(cls, *args, **kwargs)
class MyClass(metaclass=MyMeta):
__init__ = init1
print(MyClass.__init__ is init1) # False
print(MyClass.__init__ is init2) # True
If the child class (the class which inherits) does not have a class constructor ( init method), the child class will call the constructor of the parent class. However, if the child class has a constructor, it will call its own constructor.
Consider the following examples:
Child class without constructor
class ParentClass:
def __init__(self, parent_arg):
self.parent_arg = parent_arg
class ChildClass(ParentClass):
def child_method(self):
print(self.parent_arg)
c = ChildClass(parent_arg="Test")
c.child_method() # Output: Test
Child class with constructor
class ChildClass(ParentClass):
def __init__(self, child_arg):
self.child_arg = child_arg
def child_method(self):
print(self.child_arg) # Output: Child Test
# This will throw an error since this attribute is created by the parent constructor
print(self.parent_arg)
c = ChildClass(child_arg="Child Test")
c.child_method()
To call the parent constructor, pass the arguments for parent class through the constructor of child class and use super() to call the constructor of parent class
def __init__(self, child_arg, parent_arg):
self.child_arg = child_arg
super().__init__(parent_arg)
print(self.parent_arg) # This will then work
if I understand your question well, you want to understand why the User class contains no __init__
method yet it was able to receive arguments, just as @snakecharmerb answered, the User class was able to receive arguments even though it has no init method of it own, this is possible because the class from which User inherited called base have all ready implemented the init method, so you can use the init method from the base class without declaring anyone explicitly. for instance if you inherit a car from your dad, you will be able to use that car even though you don't have a car you bought for yourself.
in the second class User1 the constructor or the init method is used to create a new instance or new row inside the table, every instance of the User1 class you create will be equivalent to a new row in the table
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(120), unique=True, index=True)
username = db.Column(db.String(20), unique=True, index=True)
hash_passwrd = db.Column(db.String(200))
def __init__(self, email, username, password):
self.email = email
self.username = username
self.hash_passwrd = generate_password_hash(password)
adams = user('adams@email.com', 'adams', 'adams@1')
ben= user('ben@email.com', 'ben', 'ben@1')
poolo= user('poolo@email.com', 'poolo', 'poolo@1')
somewhere in your in your code you will have your database object
db.session.add_all([adams, ben, poolo])
db.session.commit()
now these three class object are now rows inside your table.
when you instaciate a class like this in flask it means you are creating a new row inside your user table, I hope this helps.
Perhaps the below little snippet helps to explain what is going on:
class A:
def __init__(self, a):
self.a = a
class B(A):
def printme(self):
print(self.a)
b = B(10)
b.printme()
result
10
class B
inherits class A
which has an __init__
method that defines self.a
, which is called when the instance B
is created which is then used in class B
method printme
.
so obviously the creation of the table happens in the base class
This is a misconception. The model class defines the structure of a table, and that table is created when Base.metadata.create_all
or similar is called. This is independent of the creation of any instances of the class.
Creating an instance of the model class - user = User(...)
is the equivalent of creating a row on the table, not the table itself. If an __init__
method assigns values to the class' attributes, these values become the row values. If no __init__
function is defined, the declarative machinery calls a default constructor (or a function passed as declarative_base
's constructor argument) to assign the values passed to the Model's constructor.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.