Python 我可以在SQLAlchemy中使用带参数的上下文敏感函数吗?

Python 我可以在SQLAlchemy中使用带参数的上下文敏感函数吗?,python,sqlalchemy,Python,Sqlalchemy,这里有一个小表格,以起始地址、结束地址和范围内的IP数的形式保存IP地址范围 class IpRange(Base): __tablename__ = 'ip_range' ip_range_id = Column(Integer, Sequence('ip_range_id_seq'), primary_key=True) start_ip = Column(String(15)) end_ip = Column(String(15)) num_ips

这里有一个小表格,以起始地址、结束地址和范围内的IP数的形式保存IP地址范围

class IpRange(Base):
    __tablename__ = 'ip_range'
    ip_range_id = Column(Integer, Sequence('ip_range_id_seq'), primary_key=True)
    start_ip = Column(String(15))
    end_ip = Column(String(15))
    num_ips = Column(Integer)
我想做的是能够使用各种样式创建对象,并让类了解如何填充自己的字段

foo = IpRange(ip='192.168.0.1')
foo = IpRange(ip='192.168.0.0/24')
foo = IpRange(ip='192.168.0.0-192.168.0.255')
编写一个可以解析各种IP地址/范围符号的函数并不难:

def parseIp(desired_format):
    ... stuff to parse any valid IP address/network format ...
    if desired_format == 'start':
        return start_ip
    if desired_format == 'end':
        return end_ip
    if desired_format == 'num_ips':
        return num_ips
我希望我可以对我的列使用
default
方法来获取每个列所需的数据:

class IpRange(Base):
    __tablename__ = 'ip_range'
    ip_range_id = Column(Integer, Sequence('ip_range_id_seq'), primary_key=True)
    start_ip = Column(String(15), default=parseIp('start'))
    end_ip = Column(String(15), default=parseIp('end'))
    num_ips = Column(Integer, default=parseIp('num_ips')
但是,这不是有效的SQLAlchemy语法。文档中提到了,但语法不允许将参数传递给函数。因此,即使我可以使用
default=parseIp
调用函数,我也无法告诉它我在寻找什么样的返回值

在SQLAlchemy的列规范中是否有这样做的方法

或者作为另一种想法,我应该将parseIp转换为一个助手脚本,只生成新的IpRange对象本身并将其返回给调用者吗?比如:

def parseIp(ipstring):
    ... parse data ...
    return IpRange(start_ip=parsed_start_ip, end_ip=parsed_end_ip, num_ips=parsed_num_ips)

>>> ipobj = parseIp('192.168.0.0/24')

只需重写构造函数。例如:

class IpRange(Base):
    def __init__(self, ip=None, **kwargs):
        if ip is not None:
            self.start_ip, self.end_ip = my_super_awesome_cidr_parser(ip)
        else:
            super(IpRange, self).__init__(**kwargs)

只需重写构造函数。例如:

class IpRange(Base):
    def __init__(self, ip=None, **kwargs):
        if ip is not None:
            self.start_ip, self.end_ip = my_super_awesome_cidr_parser(ip)
        else:
            super(IpRange, self).__init__(**kwargs)

好极了我不完全理解它是如何工作的(最后一行特别神秘),但它确实工作。谢谢大家!@GeorgeAdams最后一行调用超类的(
Base
)构造函数,允许您使用默认行为,即通过关键字参数设置属性(例如
IpRange(start_ip=“…”,end_ip=“…”)
)。
super()
的文档是。我想我明白了。正确的做法(如果没有指定“ip”)是以传统方式创建
IpRange
对象(
foo=IpRange(start_ip=“…”)
)。我想我们需要为
IpRange
使用原始的
\uuuu init\uuuu
,但我相信你告诉我的是,IpRange从来没有
\uuu init\uuuuu
,只有一个用于
Base
。还有一个问题-为什么要调用
super(IpRange,self)
而不仅仅是
super(IpRange)
?@GeorgeAdams简短的回答:这就是你应该如何调用超类。答案很长:它与多重继承有关。处理多重继承时,解析方法的顺序称为方法解析顺序(mro),不能直接从类本身推断。例如,
class Foo(IpRange,Bar):pass
的顺序为
Foo
IpRange
Bar
Base
。正如您所看到的,您调用哪个
\uuuuu init\uuuu
方法取决于您拥有的对象,而不仅仅是类本身。太棒了!我不完全理解它是如何工作的(最后一行特别神秘),但它确实工作。谢谢大家!@GeorgeAdams最后一行调用超类的(
Base
)构造函数,允许您使用默认行为,即通过关键字参数设置属性(例如
IpRange(start_ip=“…”,end_ip=“…”)
)。
super()
的文档是。我想我明白了。正确的做法(如果没有指定“ip”)是以传统方式创建
IpRange
对象(
foo=IpRange(start_ip=“…”)
)。我想我们需要为
IpRange
使用原始的
\uuuu init\uuuu
,但我相信你告诉我的是,IpRange从来没有
\uuu init\uuuuu
,只有一个用于
Base
。还有一个问题-为什么要调用
super(IpRange,self)
而不仅仅是
super(IpRange)
?@GeorgeAdams简短的回答:这就是你应该如何调用超类。答案很长:它与多重继承有关。处理多重继承时,解析方法的顺序称为方法解析顺序(mro),不能直接从类本身推断。例如,
class Foo(IpRange,Bar):pass
的顺序为
Foo
IpRange
Bar
Base
。如您所见,您调用的
\uuuu init\uuu
方法取决于您拥有的对象,而不仅仅是类本身。