Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何重写python3 uuu sub uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;不改变_Python_Python 3.x_Datetime_Subclass - Fatal编程技术网

如何重写python3 uuu sub uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;不改变

如何重写python3 uuu sub uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;不改变,python,python-3.x,datetime,subclass,Python,Python 3.x,Datetime,Subclass,我正在尝试对datetime类进行子类化,以便我的主代码看起来更干净。但是,对我的子类执行任何算术操作都会将数据类型更改回datetime.datetime 我使用了我的原始代码,并将其简化为一个最小的示例 from datetime import datetime, timedelta class worldtime(datetime): UTC = True tz_offset = timedelta(hours = 4) def __new__(cls, *args,

我正在尝试对datetime类进行子类化,以便我的主代码看起来更干净。但是,对我的子类执行任何算术操作都会将数据类型更改回datetime.datetime

我使用了我的原始代码,并将其简化为一个最小的示例

from datetime import datetime, timedelta

class worldtime(datetime):
   UTC = True
   tz_offset = timedelta(hours = 4)

   def __new__(cls, *args, **kwargs):
      #kwargs['tzinfo'] = dateutil.tz.tzutc()
      return super().__new__(cls, *args, **kwargs)

   def is_UTC(self):
      return self.UTC

   def to_local(self):
      print(f"type(self): {type(self)}")
      if self.UTC is True:
         self = self - self.tz_offset
         print(f"type(self): {type(self)}")
         self.UTC = False
         return self

dt = worldtime(2019, 8, 26, 12, 0, 0)
print (f"dt = {dt}   is_UTC(): {dt.is_UTC()}")
print (f"type(dt): {type(dt)}")
print (f"dir(dt): {dir(dt)}")
dt = dt.to_local()
当我减去tz_偏移量timedelta时,对象的类型将变回datetime.datetime:

dt = 2019-08-26 12:00:00   is_UTC(): True
type(dt): <class '__main__.worldtime'>
dir(dt): ['UTC', '__add__', '__class__', '__delattr__', '__dict__', 
'__dir__', '__doc__', '__eq__', '__format__', '__ge__', 
'__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', 
'__le__', '__lt__', '__module__', '__ne__', '__new__', '__radd__', 
'__reduce__', '__reduce_ex__', '__repr__', '__rsub__', '__setattr__', 
'__sizeof__', '__str__', '__sub__', '__subclasshook__', '__weakref__', 
'astimezone', 'combine', 'ctime', 'date', 'day', 'dst', 'fold', 
'fromisoformat', 'fromordinal', 'fromtimestamp', 'hour', 'is_UTC', 
'isocalendar', 'isoformat', 'isoweekday', 'max', 'microsecond', 'min', 
'minute', 'month', 'now', 'replace', 'resolution', 'second', 'strftime', 
'strptime', 'time', 'timestamp', 'timetuple', 'timetz', 'to_local', 
'today', 'toordinal', 'tz_offset', 'tzinfo', 'tzname', 'utcfromtimestamp', 
'utcnow', 'utcoffset', 'utctimetuple', 'weekday', 'year']
type(self): <class '__main__.worldtime'>
type(self): <class 'datetime.datetime'>
Traceback (most recent call last):
  File "testwt.py", line 33, in <module>
    dt.to_local()
  File "testwt.py", line 27, in to_local
    self.UTC = False
AttributeError: 'datetime.datetime' object has no attribute 'UTC'
dt=2019-08-26 12:00:00是UTC():真
类型(dt):
目录(dt):[‘UTC’、‘添加’、‘类别’、‘delattr’、‘dict’,
"目录","文件","等式","格式","通用",,
“\uuuu getattribute”、“\uuu gt\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,
"乐","乐","乐","乐","乐","乐","乐","乐","乐","乐","乐,
"减少","减少","增加","报告","重组","设置属性",,
"大小","str","sub","subclass hook","weakref",,
‘astimezone’、‘combine’、‘ctime’、‘date’、‘day’、‘dst’、‘fold’,
“fromisoformat”、“fromordinal”、“fromtimestamp”、“hour”、“is_UTC”,
“isocalendar”、“isoformat”、“isoweekday”、“max”、“microsecond”、“min”,
‘分钟’、‘月份’、‘现在’、‘替换’、‘决议’、‘秒’、‘strftime’,
“strtime”、“time”、“timestamp”、“timetuple”、“timetz”、“to_local”,
'today'、'toordinal'、'TZU offset'、'tzinfo'、'tzname'、'utcfromtimestamp',
“utcnow”、“utcoffset”、“utctimetuple”、“工作日”、“年份”]
类型(自我):
类型(自我):
回溯(最近一次呼叫最后一次):
文件“testwt.py”,第33行,在
dt.to_local()
文件“testwt.py”,第27行,在本地
self.UTC=False
AttributeError:“datetime.datetime”对象没有属性“UTC”
我可以承认,我对python中的子类并不熟悉。虽然我看到其他帖子似乎都在谈论这个问题,但没有可以效仿的例子。我所看到的最好的情况是,我必须重写_sub__)操作符,但我不确定如何做,并确保返回的对象是正确的类型。同样,没有任何清晰的代码示例可供使用


更新:更正了示例代码中的一个小错误,因为worldtime.to_local()需要将新实例返回主代码。

重要的一行是这一行,在
to_local()方法中:

self = self - self.tz_offset
您没有更改
self
(此
worldtime
对象)以使其现在表示本地时间,而是将其实际设置为一个全新的对象,特别是
self-self.tz_offset
的结果

那么为什么这个结果不是一个
worldtime
对象呢? 请注意,此计算中的对象类型为
worldtime
-
timedelta
。目前您还没有指定如何在
worldtime
类上执行减法,因此
worldtime
自动从其父类继承减法行为(
datetime
)。但这意味着它将被视为普通的
datetime
对象(毕竟,它实际上是一个
datetime
,只有几个额外的属性和方法)

因此,Python执行一个
datetime
-
timedelta
计算,结果是一个
datetime
对象,然后将其分配给
self
。这就是为什么您的
worldtime
对象似乎正在“更改”为
datetime

我们怎样才能让它工作? 有两种选择:

1)更新对象而不是创建新对象

如果我们知道我们的偏移量总是只有几个小时,我们可以这样做:

def到_本地(自):
如果self.UTC为True:
self.hour=self.hour+self.tz_offset.hours
self.UTC=False
但是这个不起作用,因为(与我最初的预期相反!):

  • tz_offset
    没有
    hours
    属性(当您创建
    timedelta
    时,它将时间存储为天、秒和微秒)
  • datetime
    对象不允许您像这样直接设置
    hour
  • 我们可以尝试更改
    \u hour
    属性(这是
    datetime
    在内部存储时间的方式),但这样更改“private”属性通常是个坏主意。另外,我们仍然需要将
    tz_offset
    转换回小时来进行计算,如果我们以后想要用小时和分钟进行偏移,会发生什么?我们需要确保我们的补偿不会带我们跨越日期边界。。。(可能还有其他我们没有想到的问题!)

    最好让
    datetime
    做它擅长的事情,因此:

    2a)让
    datetime
    处理减法运算,但将结果转换回
    worldtime

    def到_本地(自):
    如果self.UTC为True:
    新时间=self-self.tz_偏移量
    自我=世界时间(
    新年,
    新时间月份,
    纽约时间日,
    纽约时间,
    新时间,分钟,
    新时代,第二次,
    )
    self.UTC=False
    
    或者,正如您所提到的,您可以定义
    \uuuu sub\uuuu()
    特殊方法来定义
    -
    操作符在
    世界时间
    对象上执行的操作

    2b)用
    \uuuu sub\uuuu()

    让我们把
    留给_local()
    作为

    def到_本地(自):
    如果self.UTC为True:
    self=self-self.tz_偏移量
    self.UTC=False
    
    但是改变
    -
    的行为方式。在这里,我们基本上将在2a中所做的工作转移到一个名为
    \uuuu sub\uuu()
    (如sub牵引力)的单独方法中。这意味着当Python点击
    -
    时,它将左操作数和右操作数分别作为
    self
    other
    传递到
    \uuuuuu()
    特殊方法中,然后返回
    RecursionError: maximum recursion depth exceeded
    
    class datetime(date):
    
        ...
    
        def __sub__(self, other):
            "Subtract two datetimes, or a datetime and a timedelta."
            if not isinstance(other, datetime):
                if isinstance(other, timedelta):  # This is True in our case
                    return self + -other  # This is calling the __add__ function
                return NotImplemented
    
            # The remainder of the __sub__ function is omitted as we are 
            # focussing on the case in which a timedelta instance is subtracted 
            # from a datetime instance.
    
        def __add__(self, other):
            "Add a datetime and a timedelta."
            if not isinstance(other, timedelta):
                return NotImplemented
            delta = timedelta(self.toordinal(),
                              hours=self._hour,
                              minutes=self._minute,
                              seconds=self._second,
                              microseconds=self._microsecond)
            delta += other
            hour, rem = divmod(delta.seconds, 3600)
            minute, second = divmod(rem, 60)
            if 0 < delta.days <= _MAXORDINAL:
                return type(self).combine(date.fromordinal(delta.days),
                                          time(hour, minute, second,
                                               delta.microseconds,
                                               tzinfo=self._tzinfo))
            raise OverflowError("result out of range")
    
    class worldtime
    
        ...
    
        @classmethod
        def combine(cls, date, time, tzinfo=True):
            "Construct a datetime from a given date and a given time."
            if not isinstance(date, _date_class):
                raise TypeError("date argument must be a date instance")
            if not isinstance(time, _time_class):
                raise TypeError("time argument must be a time instance")
            if tzinfo is True:
                tzinfo = time.tzinfo
            return cls(date.year, date.month, date.day,
                       time.hour, time.minute, time.second, time.microsecond,
                       tzinfo, fold=time.fold)
    
    class worldtime:
    
        ...
    
        def __sub__(self, other):
            # the subtraction will turn sub into an instance of datetime
            # as we‘re calling the original subtraction function of datetime
            sub = super(worldtime, self).__sub__(other)
    
            # timetuple returns the parameters (year, month, day, etc.) 
            # and we need the first six parameters only to create a new instance.
            return worldtime(*sub.timetuple()[:6])