我在Python 3中有以下代码片段:
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy import Column, Integer, String, Unicode, UnicodeText
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method
import arrow
datetimeString_format = {
"UTC": "%Y-%m-%d %H:%M:%S+00:00",
"local_with_timezoneMarker": "%Y-%m-%d %H:%M:%S %Z",
"local_without_timezoneMarker": "%Y-%m-%d %H:%M:%S"
}
dateString_format = "%Y-%m-%d"
class My_TimePoint_Mixin:
# define output formats:
datetimeString_inUTC_format = "%Y-%m-%d %H:%M:%S+00:00"
datetimeString_naive_format = "%Y-%m-%d %H:%M:%S"
# instrumented fields:
_TimePoint_in_database = Column('timepoint', String, nullable=False)
_TimePoint_in_database_suffix = Column(
'timepoint_suffix', String, nullable=False)
@hybrid_property
def timepoint(self):
twoPossibleType_handlers = [
self._report_ACCRT_DATE,
self._report_ACCRT_DATETIME
]
for handler in twoPossibleType_handlers:
print("handler: ", handler)
try:
return handler(self)
except (AssertionError, ValueError) as e:
logging.warning("Try next handler!")
@timepoint.setter
def timepoint(self, datetimepointOBJ):
handlers_lookup = {
datetime.datetime: self._set_ACCRT_DATETIME,
datetime.date: self._set_ACCRT_DATE
}
this_time = type(datetimepointOBJ)
this_handler = handlers_lookup[this_time]
print("handler: ", this_handler)
this_handler(datetimepointOBJ)
def _report_ACCRT_DATE(self):
"""Accurate Date"""
assert self._TimePoint_in_database_suffix == "ACCRT_DATE"
date_string = self._TimePoint_in_database
dateString_format = "%Y-%m-%d"
# return a datetime.date
return datetime.datetime.strptime(date_string, dateString_format).date()
def _report_ACCRT_DATETIME(self):
"""Accurate DateTime"""
assert self._TimePoint_in_database_suffix in pytz.all_timezones_set
datetimeString_inUTC = self._TimePoint_in_database
utc_naive = datetime.datetime.strptime(
datetimeString_inUTC, self.datetimeString_inUTC_format)
utc_timepoint = arrow.get(utc_naive, "utc")
# localize
local_timepoint = utc_timepoint.to(self._TimePoint_in_database_suffix)
# return a datetime.datetime
return local_timepoint.datetime
def _set_ACCRT_DATETIME(self, datetimeOBJ_aware):
assert isinstance(datetimeOBJ_aware, datetime.datetime), "Must be a valid datetime.datetime!"
assert datetimeOBJ_aware.tzinfo is not None, "Must contain tzinfo!"
utctime_aware_arrow = arrow.get(datetimeOBJ_aware).to('utc')
utctime_aware_datetime = utctime_aware_arrow.datetime
store_datetime_string = utctime_aware_datetime.strftime(
self.datetimeString_inUTC_format)
self._TimePoint_in_database = store_datetime_string
def _set_ACCRT_DATE(self, dateOBJ):
store_date_string = dateOBJ.isoformat()
self._TimePoint_in_database = store_date_string
由于某种原因,getter的处理程序被视为普通函数而不是方法,因此需要明确地提供'self'作为其参数。
是否因为循环?还是因为try...except
结构?为什么在同一个类中,处理程序的处理方式不同? (setter的处理程序被视为预期的绑定方法。)
答案 0 :(得分:1)
您所拥有的不是常规5.0
,您有SQLAlchemy @hybrid_property
object。在那里引用文档:
“hybrid”表示该属性具有在类级别和实例级别定义的不同行为。
和
在处理
import urllib2 import csv import geoip2.database db = geoip2.database.Reader("GeoLite2-City.mmdb") target_url="http://myip/all.txt" data = urllib2.urlopen(target_url) for line in data: try: response = db.city(line.strip()) print line.strip(), response.country.name, response.country.iso_code, response.location.longitude, response.location.latitude exception: pass
类本身时,property
描述符在给定Interval
类作为参数的情况下评估函数体,当使用SQLAlchemy表达式求解时,返回一个新的SQL表达式:hybrid_property
因此,该属性用于双容量,包括实例和类。
如果属性在类本身上使用,则Interval
绑定到({1}}的子类,并且方法不受约束。在这种情况下,没有任何内容可以将绑定到,因为没有实例。
在对>>> print Interval.length
interval."end" - interval.start
getter进行编码时,您必须考虑到这一点(setter仅适用于实例上的 情况)。例如,self
和My_TimePoint_Mixin
开头的断言不会成立。
通过使用hybrid_property
装饰器为后者声明一个单独的getter,可以区分实例大小写和表达式(在类上)的情况:
_report_ACCRT_DATE
然后SQLAlchemy将使用_report_ACCRT_DATETIME
类方法进行hybrid_property.expression
使用,并仅在@hybrid_property
def timepoint(self):
twoPossibleType_handlers = [
self._report_ACCRT_DATE,
self._report_ACCRT_DATETIME
]
for handler in twoPossibleType_handlers:
print("handler: ", handler)
try:
return handler(self)
except (AssertionError, ValueError) as e:
logging.warning("Try next handler!")
@timepoint.expression
def timepoint(cls):
# return a SQLAlchemy expression for this virtual column
实例访问时使用原始getter。请参阅Defining Expression Behavior Distinct from Attribute Behavior section。