应用于python中类实例的方法//将方法应用于python中类的实例

应用于python中类实例的方法//将方法应用于python中类的实例,python,class,methods,Python,Class,Methods,我开始用python创建类,我对这些术语感到非常困惑,所以我找不到问题的答案,因为我不知道如何提问,因此这篇文章的标题是双重的。我将尝试用以下代码澄清我不知道如何提问的问题: 我想在一个简单类中创建一个方法: class SimpleClass: add(self,Value) #Magic goes here SC=SimpleClass() 该方法应等同于向类中添加新变量: SC.NewVariableInsideTheClass="test" 但通过一种方法,

我开始用python创建类,我对这些术语感到非常困惑,所以我找不到问题的答案,因为我不知道如何提问,因此这篇文章的标题是双重的。我将尝试用以下代码澄清我不知道如何提问的问题:

我想在一个简单类中创建一个方法:

class SimpleClass:
    add(self,Value)
        #Magic goes here

SC=SimpleClass()
该方法应等同于向类中添加新变量:

SC.NewVariableInsideTheClass="test"
但通过一种方法,例如:

SC.NewVariableInsideTheClass.add("test")
在这两种情况下,NewVariableInsideTheClass以前都不存在,我第一次在类中创建该变量

因此,该方法应该首先创建不存在的实例,我认为这是类中变量的名称,然后将其值设置为test,但我真的找不到/搜索如何做到这一点

哪一个是我需要的正确问题

多谢各位

---------编辑-----------

好的,所以我想做的是在执行以下操作时获得相同的结果:

SC.NewVariableInsideTheClass.add("test")
SC.NewVariableInsideTheClass.add("test")
在进行以下工作时:

SC.NewVariableInsideTheClass.add("test")
SC.NewVariableInsideTheClass.add("test")
但是这两项都必须在类外完成,新的VariableInsideTheClass是第一次使用!这里的目标是将类用作变量存储,例如,当一个变量第一次被使用时,会发生一些事情,如果它已经以SC.NewVariableInsideTheClass的形式存在,我将能够以不同的方式使用它。 希望这是更具体的现在

二次编辑;原因-------------

哇,你回答的质量和细节给我留下了深刻的印象,对此我非常感激!我想让你知道我想要这个的原因:我现在正在创建一个简单的python脚本IDE,主要是为了学习python,还没有有用的东西。因此,该代码的基础是,它会在此过程中创建新的变量。由于程序也将创建函数,因此我创建和处理变量的第一个解决方案是将所创建程序中的所有变量设置为全局变量,并在每个新函数中再次调用它们。那段代码很难看,所以我决定学习并使用一个类,但由于每个程序中的变量不同,我想标准化函数creationi我不需要知道它是否是第一个函数,是否需要初始化任何变量,或者它们是否已经存在,能够: -在一个名为变量的列表中存储一个新变量,即使它不存在,我也可以轻松访问它的名称 -能够使用新值作为列表中的新项扩展以前的变量 -能够检索这些值 在没有使用globals的情况下,我发现了这个解决方案。实际上,我修改了您的代码,现在我使用您的代码,但是我没有命名add,而是命名append,因此我可以自由地执行以下操作:

SC.NewVar.append'this is new value' SC.NewVar.append'this is new value'


第一次,它将被创建,因为它不存在,但是第二次附加新值,因此,我将能够调用它/使用它,或者从自动生成的代码中的任何其他函数中使用它:

让我们用add方法声明一个类ABC

class ABC(object):
    def add(self, var):
         self.new_var = var
现在add是instance方法,从而完成了您要做的事情,即在instance方法中声明一个实例变量

 a = ABC()
 # Make an instance
 a.add('test')
 # created a new variable inside instance
 a.new_var
 'test'

让我们用add方法声明一个类ABC

class ABC(object):
    def add(self, var):
         self.new_var = var
现在add是instance方法,从而完成了您要做的事情,即在instance方法中声明一个实例变量

 a = ABC()
 # Make an instance
 a.add('test')
 # created a new variable inside instance
 a.new_var
 'test'
免责声明:我不知道你为什么要这样做。如果要使用setattr动态创建属性,应该足够了:

SC = SimpleClass()
setattr(SC, 'your_new_attribute_name', 'test')
无论如何,有一种简单的方法可以使用帮助器类获得所需的内容:

In [1]: class SimpleClass:
   ...:     def __getattr__(self, attr):
   ...:         return AttributeSetter(self, attr)
   ...: class AttributeSetter:
   ...:     def __init__(self, inst, attr):
   ...:         self._inst = inst
   ...:         self._attr = attr
   ...:     def add(self, value):
   ...:         setattr(self._inst, self._attr, value)
   ...:         

In [2]: SC = SimpleClass()

In [3]: SC.new_attr.add('test')

In [4]: SC.new_attr
Out[4]: 'test'
关于你的评论。如果您询问是否可以编写SimpleClass,以便:

SC.new_attr
SC.new_attr
返回字符串“test”,在调用Sc.new\u attr.add“test”调用后:

SC.new_attr.add('other')
是这样的:

SC.new_attr
SC.new_attr
现在返回字符串'other',然后答案是:不,这是不可能的

不可能编写这样的类,即以下情况不会生成AttributeError:

dis模块允许我们查看解释器正在执行的字节码。 注意有两个不同的LOAD_ATTR字节码。 如您所见,解释器首先获取新的_attr属性,然后作为一个完全独立的操作检索add属性

现在,SC类只能修改第一个属性accessi.e的行为。访问新属性的权限。它无法知道下一个字节码将访问add,因此唯一明智的做法是返回已设置的字符串

对检索到的值执行以下属性访问,即add。这意味着解释器将查找字符串的add属性,该属性显然不存在

避免此AttributeError的唯一方法是返回具有add方法的对象,但这意味着:

In [6]: SC.new_attr
Out[6]: 'test'
会 失败,因为我们将返回不同的对象,而不是返回字符串测试

解决这个问题的一种方法是返回一个对象,该对象有一个add方法和一个value属性,这样我们可以得到如下结果:

In [12]: SC.new_attr
Out[12]: <__main__.TheClass at 0x7fac44727a90>

In [13]: SC.new_attr.value
Out[13]: 'test'

In [14]: SC.new_attr.add('other')

In [15]: SC.new_attr.value
Out[15]: 'other'
另一种解决方案是编写此类,使其行为类似于stringwe甚至可以将str子类化,但不要这样做!子类化内置从来都不是正确的做法,如果您在不知道确切后果的情况下这样做,您将遇到问题,并且很难发现和解决这些问题,但这意味着代码将变得更加复杂,必须实现string支持的所有操作,这意味着实现大约80-90-100个方法

免责声明:我不知道你为什么要这么做。如果要使用setattr动态创建属性,应该足够了:

SC = SimpleClass()
setattr(SC, 'your_new_attribute_name', 'test')
无论如何,有一种简单的方法可以使用帮助器类获得所需的内容:

In [1]: class SimpleClass:
   ...:     def __getattr__(self, attr):
   ...:         return AttributeSetter(self, attr)
   ...: class AttributeSetter:
   ...:     def __init__(self, inst, attr):
   ...:         self._inst = inst
   ...:         self._attr = attr
   ...:     def add(self, value):
   ...:         setattr(self._inst, self._attr, value)
   ...:         

In [2]: SC = SimpleClass()

In [3]: SC.new_attr.add('test')

In [4]: SC.new_attr
Out[4]: 'test'
关于你的评论。如果您询问是否可以编写SimpleClass,以便:

SC.new_attr
SC.new_attr
返回字符串“test”,在调用Sc.new\u attr.add“test”调用后:

SC.new_attr.add('other')
是这样的:

SC.new_attr
SC.new_attr
现在返回字符串'other',然后答案是:不,这是不可能的

不可能编写这样的类,即以下情况不会生成AttributeError:

dis模块允许我们查看解释器正在执行的字节码。 注意有两个不同的LOAD_ATTR字节码。 如您所见,解释器首先获取新的_attr属性,然后作为一个完全独立的操作检索add属性

现在,SC类只能修改第一个属性accessi.e的行为。访问新属性的权限。它无法知道下一个字节码将访问add,因此唯一明智的做法是返回已设置的字符串

对检索到的值执行以下属性访问,即add。这意味着解释器将查找字符串的add属性,该属性显然不存在

避免此AttributeError的唯一方法是返回具有add方法的对象,但这意味着:

In [6]: SC.new_attr
Out[6]: 'test'
将失败,因为我们将返回不同的对象,而不是返回字符串测试

解决这个问题的一种方法是返回一个对象,该对象有一个add方法和一个value属性,这样我们可以得到如下结果:

In [12]: SC.new_attr
Out[12]: <__main__.TheClass at 0x7fac44727a90>

In [13]: SC.new_attr.value
Out[13]: 'test'

In [14]: SC.new_attr.add('other')

In [15]: SC.new_attr.value
Out[15]: 'other'

另一种解决方案是编写此类,使其行为类似于stringwe甚至可以将str子类化,但不要这样做!子类化内置从来都不是正确的做法,如果您在不知道确切后果的情况下这样做,您将遇到问题,并且很难发现和解决这些问题,但这意味着代码将变得更加复杂,必须实现string支持的所有操作,这意味着实现大约80-90-100个方法

您是否正在尝试创建动态变量?。。这个问题的目的是什么,非常模糊。你能解释一下你为什么要这样做吗?这可能是可能的,但它打破了很多关于Python如何工作的期望。是的,我为含糊不清感到抱歉,但我真的不知道怎么问它,我将对答案进行评论并指定更多内容。我编辑问题以便能够更好地定义它。您是否试图完成动态变量的创建?。。这个问题的目的是什么,非常模糊。你能解释一下你为什么要这样做吗?这可能是可能的,但它打破了很多关于Python如何工作的期望。是的,我很抱歉含糊不清,但我真的不知道怎么问它,我将对答案进行评论并指定更多我编辑问题以便能够更好地定义它OK,非常感谢这是一个开始,但我忘了好好解释:我希望new_var是一个动态名称,不是在类内声明,而是在类外声明,直接通过调用itOk,非常感谢这是一个开始,但我忘了好好解释:我希望new_var是一个动态名称,不是在类内声明,而是在类外声明,直接打电话给我,非常感谢。我还有一个问题,如果你做两次SC.new_attr.add'test',它是否会将new_attr重新设置为值'test',而不是尝试将值设置为str?@iwantdecks更新。简而言之,你不能完全做你想做的事。另外,我想强调的是:您试图做的是非常糟糕的代码实践。可以尝试一下这个方法来了解在python中可以做什么和不能做什么,但是不要在任何项目/生产代码中使用它!非常感谢你。我还有一个问题,如果你做两次SC.new_attr.add'test',它是否会将new_attr重新设置为值'test',而不是尝试将值设置为str?@iwantdecks更新。简而言之,你不能完全做你想做的事。另外,我想强调的是:您试图做的是非常糟糕的代码实践。可以试试 这件事需要知道在python中可以做什么和不能做什么,但是不要在任何项目/生产代码中使用它!