2016-09-14 59 views
0

我在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 

出於某種原因,吸氣劑的處理程序被視爲一個普通的功能,而不是一種方法,因此有必要明確規定「自我」作爲它的參數。

是因爲循環?或因爲try...except結構?爲什麼在同一個班級中,處理程序的處理方式有所不同? (setter的處理程序按預期方式被視爲綁定方法)。

+0

看,這很重要,因爲我現在看到你有一個'hybrid_property'。這可以在一個實例(綁定方法)和* class *上執行(其中方法將被解除綁定,*不能綁定*)。 –

回答

1

你有什麼是不是經常property在這裏,你有一個SQLAlchemy @hybrid_property object。引用該處的文檔:

「混合」意味着屬性具有在類級別和實例級別定義的不同行爲。

當與Interval類本身處理,所述hybrid_property描述符的計算結果給出的Interval類作爲參數,當其與SQLAlchemy的表達力學評價返回一個新的SQL表達式函數體:

>>> print Interval.length 
interval."end" - interval.start 

所以財產是一個雙重能力使用,無論是在實例上,還是在課堂上。

在屬性本身被使用的情況下,self被綁定到(的子類)My_TimePoint_Mixin並且方法未被綁定。在這種情況下沒有什麼可以綁定,因爲沒有實例。

編碼hybrid_property吸氣劑時,必須考慮到這一點(設置器僅適用於實例情況下的)。例如,您在_report_ACCRT_DATE_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 

SQLAlchemy的將然後使用@timepoint.expression類的方法爲My_TimePoint_Mixin.timepoint的使用,並且使用原始的getter只對My_TimePoint_Mixin().timepoint實例進行訪問。請參閱Defining Expression Behavior Distinct from Attribute Behavior section

+0

似乎沒有SQL表達式等價於泛型函數調度構造。 SQL表達式中最接近的東西似乎是func的CASE。任何人都可以提供比「CASE」更好的解決方案? –

+0

@ JinghuiNiu:不,我會說你在這裏遇到了'CASE'。 –

相關問題