简体   繁体   English

如何创建一个包含 split() 的 hybrid_property?

[英]How to create a hybrid_property that incorporates split()?

Given the simple table:鉴于简单的表:

class Result(Base):
    __tablename__ = "result"

    id_ = Column(Integer, primary_key=True, autoincrement=True)
    result = Column(String(20))

Where result records are of the form 6-1 , 7-5 etc. result记录的格式为6-17-5等。

I'd like to create a property that sums the integers in the result field, eg 6-1 would be 7 .我想创建一个对result字段中的整数求和的属性,例如6-1将是7 I've tried the following:我尝试了以下方法:

@hybrid_property
def sum_games(self):
    return sum(int(s) for s in self.result.split("-"))

But I get the error:但我收到错误:

Exception has occurred: AttributeError
Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Result.result has an attribute 'split'

I understand enough of Python to get that self.result isn't a string so I can't use the split() method.我对 Python 的了解足以让self.result不是字符串,所以我不能使用split()方法。 Is there a way to convert this to a string?有没有办法将其转换为字符串? I've tried str(self.result) but that returns Result.result .我试过str(self.result)但它返回Result.result

Maybe there's another way to achieve the output I'm looking for?也许还有另一种方法可以实现我正在寻找的输出?

Worth me mentioning that the result strings are actually a little more complicated than the examples above but I always need the split() method so I've simplified for this post.值得一提的是, result字符串实际上比上面的例子稍微复杂一些,但我总是需要split()方法,所以我已经简化了这篇文章。

Hybrid properties have two parts, a Python part and a SQL part, which is denoted with the decorator @sum_games.expression .混合属性有两部分,Python 部分和 SQL 部分,用装饰器@sum_games.expression If you don't specify that expression counterpart, the hybrid property itself is used in SQL as well.如果您不指定该expression对应项,则混合属性本身也会在 SQL 中使用。 But .split() and all the other python functions are unknown there, so try the following instead:但是.split()和所有其他 python 函数在那里是未知的,所以请尝试以下操作:

@hybrid_property
def sum_games(self):
    return sum(int(s) for s in self.result.split("-"))

@sum_games.expression
def sum_games(cls):  # yes this is a class method for some reason
    sum_part_array = func.regexp_split_to_array(cls.result, '-')
    sum_parts = func.unnest(sum_part_array).alias("y")
    sum_clause = func.sum(cast(column("y"), Integer)

    return select([sum_clause]).select_from(sum_parts).as_scalar()

With translates to the SQL:与转换为 SQL:

SELECT (SELECT SUM(y::int) FROM unnest(regexp_split_to_array(x, '-')) as y)
FROM (values ('6-1'), ('7-1')) as bla(x)

This works with PostgreSQL, if you use a different dialect, the same logic should hold with the equivalent functions这适用于 PostgreSQL,如果您使用不同的方言,则相同的逻辑应该适用于等效的功能

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM