簡體   English   中英

屬性在對象內部正確設置,但不能在外部訪問

[英]Property set correctly inside an object but not accessible outside

我正在使用Python3在python pyramid下工作。

我有一個看起來像這樣的模型:

class OneTimeCode(Base):
    __tablename__ = 'otc_one_time_codes'
    otc_one_time_code_id = Column(Integer, primary_key=True)
    otc_one_time_code = Column(String(32))
    otc_usr_user_id = Column(Integer, ForeignKey('usr_users.usr_user_id'), nullable=True)
    otc_expire_time = Column(DateTime)

    def __init__(self, otc_usr_user_id, otc_expire_time=None):
        self.otc_usr_user_id = otc_usr_user_id
        if otc_expire_time is None:
            self.otc_expire_time = (datetime.now() + timedelta(6*365/12)).isoformat()
        else:
            self.otc_expire_time = otc_expire_time

    @classmethod
    def get_code(self, hlength=6):    
        seed = datetime.now() + timedelta(random.randrange(1,10000))
        tmp_hash = hashlib.md5(seed.strftime("%Y-%m-%d %H:%M:%S.%F").encode('utf-8')).hexdigest()

        if hlength == 32:
            self.otc_one_time_code = tmp_hash
        else:  
            self.otc_one_time_code = tmp_hash[0 : hlength]

        print(self.otc_one_time_code)

問題是,當我實例化這些對象之一,然后顯式調用get_code時,最后的打印行將代碼成功打印到屏幕上。

但是,在我看來,如果我明確嘗試打印該屬性,則該屬性為“無”

這是我的視圖代碼:

   otc = OneTimeCode(
        otc_usr_user_id = user.usr_user_id
    )

    otc.get_code()
    pprint.pprint(vars(otc))
    session.add(otc)

控制台輸出如下所示:

0d097c 
{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x50877d0>,  'otc_expire_time': '2015-02-13T10:56:14.244447',  'otc_usr_user_id': 1} 2014-08-14 22:56:14,245 
INFO  [sqlalchemy.engine.base.Engine][Dummy-2] INSERT INTO otc_one_time_codes (otc_one_time_code, otc_usr_user_id, otc_expire_time) VALUES (%(otc_one_time_code)s, %(otc_usr_user_id)s, %(otc_expire_time)s) RETURNING otc_one_time_codes.otc_one_time_code_id 2014-08-14 22:56:14,245 
INFO  [sqlalchemy.engine.base.Engine][Dummy-2] {'otc_one_time_code': None, 'otc_expire_time': '2015-02-13T10:56:14.244447', 'otc_usr_user_id': 1} 2014-08-14 22:56:14,247 
INFO  [sqlalchemy.engine.base.Engine][Dummy-2] COMMIT

您可以在模型內部看到值:0d097c,以及看起來不存在該屬性的pprint對象。

為什么我無法訪問此屬性?

看起來您應該使用@property而不是OTC ,但是似乎您不想每次都計算它!

# for all the docstrings, let multi = Multi(2)
class Multi(object):
    def __init__(self, attribute):
        """When instantiated, set self.attribute to attribute"""
        self.attribute = attribute

    @property
    def attribute_times_ten(self):
        """accessed via multi.attribute_times_ten
        and will return 20. Use properties to signify
        a variable that requires some work done to it
        that needs to calculated each time it's called."""
        return attribute_times_ten

    @classmethod
    def times_ten(cls, num):
        """Not the best example, but a @classmethod will
        give the class as its first argument, NOT the
        instance. This is useful in lots of constructor
        settings, e.g. CreateClass.fromstring("attributes")"""
        return num * 5

    def generate_number(self, multiplier):
        """This is just a normal method. This is what I think
        you want, tbh, and you should probably call it in your
        __init__ method since you NEED this to run in your OTC
        for it to work as intended. Methods (like properties)
        are automagically passed the instance as the first
        argument, so we can CHANGE self.attribute with that."""
        self.attribute = self.attribute * multiplier

文檔字符串應具有自我描述性,但:

multi = Multi(2)
multi.attribute_times_ten # returns 20
Multi.times_ten(8) # returns 80, note the capital M!
multi.generate_number(3) # self.attribute is now 6
multi.attribute_times_ten # returns 60

在實際情況下,您可能需要以上所有條件:

class _Tile(object):
    def __init__(self, x, y):
        """A naive implementation of Tile that doesn't care
        what its side length is and doesn't have any properties
        to hide its attributes"""
        self.x = x
        self.y = y
    @classmethod
    def tiles_to_pixels(cls, tile):
        return cls(tile._x * tile.side_length, tile._y * tile.side_length)
    @classmethod
    def tiles_to_tiles(cls, tile):
        return cls(tile._x, tile._y)

class Tile(object):
    def __init__(self, x, y, side_length):
        """A tile object in a map"""
        self._x = x # x-coord in tiles
        self._y = y # y-coord in tiles
        self.side_length = side_length # pixels per tile
    @property
    def in_pixels(self):
        """self.in_pixels returns an object whose .x and .y
        correspond to the x and y position IN PIXELS of the
        top-left corner of the tile."""
        _tile = _Tile.tiles_to_pixels(self)
        return _tile
    @property
    def in_tiles(self):
        """self.in_tiles returns an object whose .x and .y
        correspond to the x and y position IN TILES of the
        top-left corner of the tile."""
        _tile = _Tile.tiles_to_tiles(self)
        return _tile
    def change_side_length(self, new_length):
        """Use to change the side length. This can break
        your whole map since it's naive, so be careful."""
        self.side_length = new_length

my_tile = Tile(0,0,32) # 32 pixel tile starting at (0,0)
my_tile.x # NameError, since it's called my_tile._x
my_tile.in_tiles.x # 0
my_tile.in_pixels.y # 0
other_tile = Tile(4,7,32) # 32 pixel tile starting at (4,7)
other_tile.y # NameError, see above
other_tile.in_tiles.y # 7
other_tile.in_pixels.x # 128

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM