简体   繁体   English

Python类self.variables

[英]Python classes self.variables

I have started learning python classes some time ago, and there is something that I do not understand when it comes to usage of self.variables inside of a class. 一段时间以前,我已经开始学习python类,在类内部使用self.variables时,我有些不了解。 I googled, but couldn't find the answer. 我用谷歌搜索,但找不到答案。 I am not a programmer, just a python hobbyist. 我不是程序员,只是python爱好者。 Here is an example of a simple class, with two ways of defining it: 这是一个简单类的示例,有两种定义方式:

1)first way: 1)第一种方式:

class Testclass:
    def __init__(self, a,b,c):
        self.a = a
        self.b = b
        self.c = c
    def firstMethod(self):
        self.d = self.a + 1
        self.e = self.b + 2
    def secondMethod(self):
        self.f = self.c + 3
    def addMethod(self):
        return self.d + self.e + self.f

myclass = Testclass(10,20,30)
myclass.firstMethod()
myclass.secondMethod()
addition = myclass.addMethod()

2)second way: 2)第二种方式:

class Testclass:
    def __init__(self, a,b,c):
        self.a = a
        self.b = b
        self.c = c
    def firstMethod(self):
        d = self.a + 1
        e = self.b + 2
        return d,e
    def secondMethod(self):
        f = self.c + 3
        return f
    def addMethod(self, d, e, f):
        return d+e+f

myclass = Testclass(10,20,30)
d, e = myclass.firstMethod()
f= myclass.secondMethod()
addition = myclass.addMethod(d,e,f)

What confuses me is which of these two is valid? 令我困惑的是这两个是有效的吗? Is it better to always define the variables inside the methods (the variables we expect to use later) as self.variables (which would make them global inside of class) and then just call them inside some other method of that class (that would be the 1st way in upper code)? 最好始终将方法内部的变量(我们希望稍后使用的变量)定义为self.variables(这将使它们在类内部成为全局变量),然后仅在该类的其他方法中调用它们(即上部代码的第一种方法)? Or is it better not to define variables inside methods as self.variables, but simply as regular variables, then return at the end of the method. 或者最好不要将方法内部的变量定义为self.variables,而只需将其定义为常规变量,然后在方法末尾返回即可。 And then "reimport" them back into some other method as its arguments (that would be 2nd way in upper code)? 然后将它们“重新导入”到其他方法作为其参数(在较高代码中为第二种方式)?

EDIT: just to make it clear, I do not want to define the self.d, self.e, self.f or d,e,f variables under the init method. 编辑:只是为了清楚起见,我不想在init方法下定义self.d,self.e,self.f或d,e,f变量。 I want to define them at some other methods like showed in the upper code. 我想用其他一些方法来定义它们,如上面代码中所示。 Sorry for not mentioning that. 对不起,我没有提及。

Both are valid approaches. 两者都是有效的方法。 Which one is right completely depends on the situation. 哪一个完全正确取决于情况。

Eg 例如

  • Where you are 'really' getting the values of a, b, c from 您“真正”从哪里获取a,b,c的值
  • Do you want/need to use them multiple times 您是否想要/需要多次使用
  • Do you want/need to use them within other methods of the class 您是否想要/在类的其他方法中使用它们
  • What does the class represent 这个班代表什么
  • Are ab and c really 'fixed' attributes of the class, or do they depend on external factors? ab和c确实是该类的“固定”属性,还是取决于外部因素?

In the example you give in the comment below: 在示例中,您在下面提供注释:

Let's say that a,b,c depend on some outer variables (for example a = d+10, b = e+20, c = f+30, where d,e,f are supplied when instantiating a class: myclass = Testclass("hello",d,e,f)) . 假设a,b,c依赖于某些外部变量(例如a = d + 10,b = e + 20,c = f + 30,其中在实例化类时提供d,e,f: myclass = Testclass("hello",d,e,f)) Yes, let's say I want to use a,b,c (or self.a,self.b,self.c) variables within other methods of the class too. 是的,假设我也想在该类的其他方法中使用a,b,c(或self.a,self.b,self.c)变量。

So in that case, the 'right' approach depends mainly on whether you expect a, b, c to change during the life of the class instance. 因此,在那种情况下,“正确”的方法主要取决于您是否期望a,b,c在类实例的生存期内发生变化。 For example, if you have a class where hte attributes (a,b,c) will never or rarely change, but you use the derived attribures (d,e,f) heavily, then it makes sense to calculate them once and store them. 例如,如果您有一个类别,其中属性(a,b,c)永远不会或很少改变,但是您大量使用派生的属性(d,e,f),则一次计算并存储它们是有意义的。 Here's an example: 这是一个例子:

class Tiger(object):
    def __init__(self, num_stripes):
        self.num_stripes = num_stripes
        self.num_black_stripes = self.get_black_stripes()
        self.num_orange_stripes = self.get_orange_stripes()
    def get_black_stripes(self):
        return self.num_stripes / 2
    def get_orange_stripes(self):
        return self.num_stripes / 2

big_tiger = Tiger(num_stripes=200)
little_tiger = Tiger(num_stripes=30)

# Now we can do logic without having to keep re-calculating values
if big_tiger.num_black_stripes > little_tiger.num_orange_stripes:
    print "Big tiger has more black stripes than little tiger has orange"

This works well because each individual tiger has a fixed number of stripes. 因为每只老虎都有固定数量的条纹,所以效果很好。 If we change the example to use a class for which instances will change often, then out approach changes too: 如果我们将示例更改为使用实例经常更改的类,那么out方法也将更改:

class BankAccount(object):
    def __init__(self, customer_name, balance):
        self.customer_name = customer_name
        self.balance = balance
    def get_interest(self):
        return self.balance / 100

my_savings = BankAccount("Tom", 500)
print "I would get %d interest now" % my_savings.get_interest()
# Deposit some money
my_savings.balance += 100
print "I added more money, my interest changed to %d" % my_savings.get_interest()

So in this (somewhat contrived) example, a bank account balance changes frequently - therefore there is no value in storing interest in a self.interest variable - every time balance changes, the interest amount will change too. 因此,在这个(有些人为设计的)示例中,银行帐户余额经常更改-因此,将利息存储在self.interest变量中没有任何价值-每次余额更改时,利息金额也会更改。 Therefore it makes sense to calculate it every time we need to use it. 因此,每次我们需要使用它时都应该进行计算。

There are a number of more complex approaches you can take to get some benefit from both of these. 您可以采用许多更复杂的方法来从这两种方法中受益。 For example, you can make your program 'know' that interest is linked to balance and then it will temporarily remember the interest value until the balance changes (this is a form of caching - we use more memory but save some CPU/computation). 例如,您可以让您的程序“知道”利息与余额相关联,然后它将暂时记住利息值,直到余额发生变化(这是一种缓存形式-我们使用更多的内存,但节省了一些CPU /运算量)。

Unrelated to original question 与原始问题无关

A note about how you declare your classes. 关于如何声明类的说明。 If you're using Python 2, it's good practice to make your own classes inherit from python's built in object class: 如果您使用的是Python 2,则最好使自己的类继承自python的内置对象类:

class Testclass(object):
    def __init__(self, printHello):

Ref https://wiki.python.org/moin/NewClassVsClassicClass Python 3 uses there new-style classes by default, so you don't need to explicitly inherit from object if using py3. 参考https://wiki.python.org/moin/NewClassVsClassicClass Python 3默认使用那里的新样式类,因此,如果使用py3,则不需要从对象显式继承。

EDITED: 编辑:

If you want to preserve the values inside the object after perform addMethod , for exmaple, if you want call addMethod again. 如果要在执行addMethod之后保留对象内部的值,例如,如果要再次调用addMethod then use the first way. 然后使用第一种方法。 If you just want to use some internal values of the class to perform the addMethod, use the second way. 如果只想使用该类的某些内部值来执行addMethod,请使用第二种方法。

You really can't draw any conclusions on this sort of question in the absence of a concrete and meaningful example, because it's going to depend on the facts and circumstances of what you're trying to do. 如果没有具体且有意义的示例,您真的无法对此类问题得出任何结论,因为这将取决于您要执行的操作的事实和情况。

That being said, in your first example, firstMethod() and secondMethod() are just superfluous. 就是说,在您的第一个示例中, firstMethod()secondMethod()只是多余的。 They serve no purpose at all other than to compute values that addMethod() uses. 除了计算addMethod()使用的值外,它们根本没有其他用途。 Worse, to make addMethod() function, the user has to first make two inexplicable and apparently unrelated calls to firstMethod() and secondMethod() , which is unquestionably bad design. 更糟糕的是,要使addMethod()函数起作用,用户必须首先对firstMethod()secondMethod()进行两个莫名其妙且显然无关的调用,这无疑是不好的设计。 If those two methods actually did something meaningful it might make sense (but probably doesn't) but in the absence of a real example it's just bad. 如果这两种方法实际上做了有意义的事情,这可能是有道理的(但可能没有意义),但是在没有实际示例的情况下,这很糟糕。

You could replace the first example by: 您可以将第一个示例替换为:

class Testclass:
    def __init__(self, a,b,c):
        self.a = a
        self.b = b
        self.c = c

    def addMethod(self):
        return self.a + self.b + self.c + 6

myclass = Testclass(10,20,30)
addition = myclass.addMethod()

The second example is similar, except firstMethod() and secondMethod() actually do something, since they return values. 第二个示例相似,不同之处firstMethod()secondMethod()实际上会执行某些操作,因为它们返回值。 If there was some reason you'd want these values separately for some reason other than passing them to addMethod() , then again, it might make sense. 如果有某种原因,你会想这些值分别比它们传递给其他一些原因addMethod()然后再次,它可能是有意义的。 If there wasn't, then again you could define addMethod() as I just did, and dispense with those two additional functions altogether, and there wouldn't be any difference between the two examples. 如果没有,则可以像我刚才那样定义addMethod() ,并且完全省去这两个附加函数,并且这两个示例之间没有任何区别。

But this is all very unsatisfactory in the absence of a concrete example. 但这在没有具体例子的情况下是非常不令人满意的。 Right now all we can really say is that it's a slightly silly class. 现在,我们真正能说的是,这有点愚蠢。

In general, objects in the OOP sense are conglomerates of data (instance variables) and behavior (methods). 通常,OOP意义上的对象是数据(实例变量) 行为(方法)的集合。 If a method doesn't access instance variables - or doesn't need to - then it generally should be a standalone function, and not be in a class at all. 如果一个方法不访问实例变量-或不需要-则通常应该是一个独立的函数,并且根本不在类中。 Once in a while it will make sense to have a class or static method that doesn't access instance variables, but in general you should err towards preferring standalone functions. 偶尔有一个不访问实例变量的类或静态方法很有意义,但是总的来说,您应该偏向于偏爱独立函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM