类修饰符在Python中练习

2024-03-29 10:07:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我从davidbeazley的视频课程Python编程语言学习Python。我陷入了这个程序,作者试图用@typed来装饰Holding类。你知道吗

不幸的是,虽然我相信我逐字复制了代码,但它似乎没有按计划工作。你知道吗

我在底部的main()中复制了所键入函数中的代码。它起了很大的作用。你知道吗

有人能给我点启发吗?非常感谢。你知道吗

from typing import Union, List, Iterator
from pprint import pprint
import csv

# Changes
# make Typed.__init__(self, name=None)
# create def typed(cls)
# decorate class Holding with @typed
# no need for the argument in String(), Integer(), Float()


class Typed:
    expected_type = object

    def __init__(self, name=None):
        self.name = name

    def __get__(self, instance, cls):
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if not isinstance(value, self.expected_type):
            raise TypeError(f'Expected {self.expected_type}')
        instance.__dict__[self.name] = value


class Integer(Typed):
    expected_type = int


class Float(Typed):
    expected_type = float


class String(Typed):
    expected_type = str


def typed(cls):
    for key, obj in vars(cls).items():
        if isinstance(obj, Typed):
            obj.name = key
            print('in typed():', obj.name)
        return cls


@typed
class Holding:
    """Use proxy __setattr__() to limit attributes to design"""
    name = String()
    shares = Integer()
    price = Float()

    def __init__(self, name, date, shares, price):
        self.name = name
        self.date = date
        self.shares = shares
        self.price = price

    def __setattr__(self, name, value):
        if name not in {'name', 'date', 'shares', 'price'}:
            raise AttributeError(f'No attribute {name}')
        super().__setattr__(name, value)

    @property
    def cost(self):
        return self.shares * self.price

    def __str__(self) -> str:
        return f'{self.shares} shares of {self.name} at {self.price}'

    def __repr__(self) -> str:
        return f'Holding({self.name}, {self.date}, {self.shares}, {self.price})'


class Portfolio:
    def __init__(self):
        self.holdings: List[Holding] = []

    def __getattr__(self, name): # provide list like behaviour
        return getattr(self.holdings, name)

    @classmethod
    def from_csv(cls, filename: str) -> 'Portfolio':
        self = cls()
        with open(filename, 'r') as f:
            rows = csv.reader(f)
            headers = next(rows)
            for row in rows:
                h: [Holding] = Holding(row[0], row[1], int(row[2]), float(row[3]))
                self.holdings.append(h)
        return self

    def total_cost(self) -> float:
        return sum([h.shares * h.price for h in self.holdings])

    def __len__(self) -> int:
        return len(self.holdings)

    def __getitem__(self, index: Union[int, str]) -> Union[Holding, List[Holding]]:
        if isinstance(index, str):
            return [h for h in self.holdings if h.name == index]
        else:
            return self.holdings[index]

    def __iter__(self) -> Iterator:
        return iter(self.holdings)


def main():
    h = Holding('ABC', '2018-01-09', 500, 3.45)
    print(h.name, h.date, h.shares, h.price, h.cost)
    # print(h.name, h.date, h.shares, h.price, h.cost)
    # portfolio = Portfolio.from_csv('portfolio.csv')
    # pprint(portfolio.holdings)
    # portfolio.append(Holding('MAC', '2011-12-01', 125, 90.0))
    # print(f'{len(portfolio)} items in the portfolio')
    # pprint(portfolio.holdings)
    try:
        h.shares = 100
        h.time = '10:05AM'
    except Exception as e:
        print(e)

    try:
        h.shares = "200"
    except Exception as e:
        print(e)
    print(h.name, h.date, h.shares, h.price, h.cost)



    for key, obj in vars(Holding).items():
        if isinstance(obj, Typed):
            obj.name = key
            print('in main(): ', obj.name)


if __name__ == '__main__':
    main()

以下是输出:

可以看出h实例是不对的。你知道吗

应为:ABC 2018-01-09 500 3.45 1725.0

3.45 2018-01-09 3.45 3.45 11.902500000000002
No attribute time
Expected <class 'int'>
100 2018-01-09 100 100 10000
in main():  name
in main():  shares
in main():  price

Tags: nameinselfobjdatereturnmaindef
1条回答
网友
1楼 · 发布于 2024-03-29 10:07:52

我发现了问题。你知道吗

def typed(cls):
    for key, obj in cls.__dict__.items():
    # for key, obj in vars(cls).items(): # Altrenative
        if isinstance(obj, Typed):
            obj.attrname = key
    return cls

返回cls的缩进错误 我还把名字改成了attrname,因为我被许多“名字”搞糊涂了,但这只是为了可读性。你知道吗

相关问题 更多 >