我有使用 __getattribute__ 时遇到问题。

huangapple go评论70阅读模式
英文:

i have a problem with using __getattribute__

问题

这是你的代码,出现了AttributeError错误:

  File "c:\Users\User\Desktop\python\book2\unit2\project6.py", line 25, in <module>
    objA = Myclass([1, 2, 3, 4, 5, "something", "word"])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\User\Desktop\python\book2\unit2\project6.py", line 13, in __init__
    self.lst.append(L[i])
    ^^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'append

错误的原因是在构造函数中,你尝试将字符串追加到一个字符串属性self.lst上,这是不合法的。你应该将它追加到self.txt,因为你的目标是构建一个包含字符串首字母的文本。

你可以将这一行:

self.lst.append(L[i])

更改为:

self.txt += L[i][0]

这应该能解决你的问题。

英文:

I have a school task that i need to do. I should create an object when constructor where when you put a list as an argument it only takes the string from the list and put them in the attribute of the class. When you try to print the list, it should only print the first characters of each string in the list. For example, if i put [1,2,3,4,"something","word"] the attribute should contain ["something","word"] and when you print it on the console it should pop up sw. I must use __getattribute__.

This is the code that I wrote

class Myclass:

    def __init__(self, L):
        self.lst = []
        self.txt = ""

        if type(L) == list:
            for i in range(len(L)):
                if type(L[i]) == str:
                    self.lst.append(L[i])

            for i in range(len(self.lst)):
                self.txt += self.lst[i][0]

    def __getattribute__(self, name):
        if name == "lst":
            return object.__getattribute__(self, "txt")
        else:
            return object.__getattribute__(self, name)


objA = Myclass([1, 2, 3, 4, 5, "something", "word"])
print(objA.lst)
print(objA.txt)

it gives me AttribureError:

  File "c:\Users\User\Desktop\python\book2\unit2\project6.py", line 25, in <module>
    objA = Myclass([1, 2, 3, 4, 5, "something", "word"])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\User\Desktop\python\book2\unit2\project6.py", line 13, in __init__
    self.lst.append(L[i])
    ^^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'append

答案1

得分: 1

I made attribute private. __getattribute__ method is used in both cases: creating object and accessing by print(objA.lst).

在创建对象时,self._lst.append(item) 调用了 __getattribute__ 方法。类似于 self.__getattribute__('_lst')

class Myclass:

    def __init__(self, L):
        self._lst = []  # 用于保存字符串列表的私有属性
        self.txt = ""

        if isinstance(L, list):
            for item in L:
                if isinstance(item, str):
                    self._lst.append(item)
                    self.txt += item[0]

    def __getattribute__(self, name):
        if name == "lst":
            return object.__getattribute__(self, "txt")
        else:
            return object.__getattribute__(self, name)


if __name__ == '__main__':
    objA = Myclass([1, 2, 3, 4, 5, "something", "word"])
    print(objA.lst)  # 输出 'sw'
英文:

I made attribute private. __getattribute__ method is used in both cases: creating object and accessing by print(objA.lst).

In the case of creating object, self._lst.append(item) calls __getattribute__ under the hood. Like self.__getattribute__('_lst')

class Myclass:

    def __init__(self, L):
        self._lst = []  # private attribute to hold the list of strings
        self.txt = ""

        if isinstance(L, list):
            for item in L:
                if isinstance(item, str):
                    self._lst.append(item)
                    self.txt += item[0]

    def __getattribute__(self, name):
        if name == "lst":
            return object.__getattribute__(self, "txt")
        else:
            return object.__getattribute__(self, name)


if __name__ == '__main__':
    objA = Myclass([1, 2, 3, 4, 5, "something", "word"])
    print(objA.lst)  # prints 'sw'

答案2

得分: 1

没有必要在列表上使用range,只需枚举列表。如下所示:

class Myclass():

    def __init__(self, L):
        self.txt = ""

        if type(L) == list:
            for s in L:
                if type(s) == str:
                    self.txt += s[0:1]

    def __getattribute__(self, name):
        if name == "lst":
            return object.__getattribute__(self, "txt")
        else:
            return object.__getattribute__(self, name)


objA = Myclass([1, 2, 3, 4, 5, "something", "word", ""])
print(objA.lst)
print(objA.txt)
英文:

There is no need to use range on lists, just enumerate the list. As follows:

class Myclass():

def __init__(self, L):
    self.txt = ""

    if type(L) == list:
        for s in L:
            if type(s) == str:
                self.txt += s[0:1]

def __getattribute__(self, name):
    if name == "lst":
        return object.__getattribute__(self, "txt")
    else:
        return object.__getattribute__(self, name)


objA = Myclass([1, 2, 3, 4, 5, "something", "word", ""])
print(objA.lst)
print(objA.txt)

答案3

得分: 0

I believe you have solved this in reverse. You do not need to construct the "txt" attribute, because that's exactly how lists print themselves. Consider:

class Myclass:

    def __init__(self, L):
        self.lst = []

        if type(L) == list:
            for i in L:
                if type(i) == str:
                    self.lst.append(i)

    def __getattribute__(self, name):
        if name == "txt":
            lst =  object.__getattribute__(self, "lst")
            return ''.join(l[0] for l in lst)
        else:
            return object.__getattribute__(self, name)


objA = Myclass([1, 2, 3, 4, 5, "something", "word"])
print(objA.lst)
print(objA.txt)

Output:

['something', 'word']
sw

Note that your design doesn't work if you add to lst later, whereas this design will.

英文:

I believe you have solved this in reverse. You do not need to construct the "txt" attribute, because that's exactly how lists print themselves. Consider:

class Myclass:

    def __init__(self, L):
        self.lst = []

        if type(L) == list:
            for i in L:
                if type(i) == str:
                    self.lst.append(i)

    def __getattribute__(self, name):
        if name == "txt":
            lst =  object.__getattribute__(self, "lst")
            return ''.join(l[0] for l in lst)
        else:
            return object.__getattribute__(self, name)


objA = Myclass([1, 2, 3, 4, 5, "something", "word"])
print(objA.lst)
print(objA.txt)

Output:

['something', 'word']
sw

Note that your design doesn't work if you add to lst later, whereas this design will.

答案4

得分: 0

在我看来,实现这个的最优雅和可读性最好的方式是通过重写collections UserList的初始化方法以及负责添加元素的所有方法,以及用于获取列表的方法,只返回第一个字母。

英文:

In my opinion most elegant and readable way to accomplish that is by overriding collections UserList init and all methods that takes care of adding elements + the one for getting list to only return first letters.

huangapple
  • 本文由 发表于 2023年7月3日 05:48:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76600925.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定