简体   繁体   中英

Calling methods within a class method in Python

I have found that when calling methods from within a method of a class I do not need to pass any variables to the method. Instead it simply inherits the attributes from that method when the method is called.

class Person(object):
    def method1(self):
        print(self.attr1)

    def method2(self):
        self.attr1 = 'attr1'
        self.method1()

This works for me. However, my first intuitive attempt consisted of the following nonfunctional code.

class Person(object):
    def method1(self, attr1):
        print(self.attr1)

    def method2(self):
        self.method1('attr1')

Even though I figured out a solution to the problem, I'm very much interested to learn the underpinnings behind this one.

EDIT: The example I am trying to understand is this:

class Converter(object):

    def split(self, x):
        self.a, self.b, self.z, self.c = self.x.split(' ')
        self.z = None
        self.a = int(self.a)

    def converter(self, unit, example):
        self.x = ''
        while self.x != 'exit':
            self.x = input("Type '50 %s' or similar, or type 'units' to view valid units; type 'exit' to return to the main menu: " % (self.example))
            if self.x == 'exit':
                break
            elif self.x == 'units':
                print(list(self.units.keys()))
            else:
                self.split(self.x)
                print(self.a / self.units[self.b] * self.units[self.c], self.c)

    def volume(self):
        self.units = { 'L': 1,
                       'mL': 1000,
                       'q': 1.05699,
                       'p': 2.11338,
                       'gal': 3.78541,
                       'oz': 33.814,
                       'ccm': 1000,
                       'cin': 61.024
                        }

        self.example = 'L to q'
        self.converter()

I don't understand why this wouldn't work:

class Converter(object):

    def split(self, x):
        self.a, self.b, self.z, self.c = self.x.split(' ')
        self.z = None
        self.a = int(self.a)

    def converter(self):
        self.x = ''
        while self.x != 'exit':
            self.x = input("Type '50 %s' or similar, or type 'units' to view valid units; type 'exit' to return to the main menu: " % (self.example))
            if self.x == 'exit':
                break
            elif self.x == 'units':
                print(list(self.units.keys()))
            else:
                self.split(self.x)
                print(self.a / self.units[self.b] * self.units[self.c], self.c)

    def volume(self):
        self.units = { 'L': 1,
                       'mL': 1000,
                       'q': 1.05699,
                       'p': 2.11338,
                       'gal': 3.78541,
                       'oz': 33.814,
                       'ccm': 1000,
                       'cin': 61.024
                        }

        self.converter({'L':2}, 'L to q')

EDIT2: Okay I think I understand now. The attributes are being attached to the instance object and I was simply not assigning the attributes that were passed onto the next function to the instance object.

In the second (and non-functional) code, you were trying to call self.attr1 from method1 , but no such attributed existed for the Person object.
method1 would have worked fine if it said print(attr1) , where attr1 is the variable that got sent in as the second argument to method1

By the way, the new code would throw an error if someone tried calling method1 on an object before method2 was called. This is because the Person object doesn't have an attr1 attribute before method2 runs.

Understanding what's going on becomes very difficult when you have similar names/string values for different things. I would suggest using different names/values for self.attr1 , attr1 and "attr1" , and it will become much more obvious why your original code wasn't working.

The way you phrase the question suggests you're misunderstanding how attributes work. Attributes pertain to the object (an instance of a class), not to the method. When you have a method like this:

def method2(self):
    self.attr1 = 'attr1'
    self.method1()

self refers to the instance that you are calling the method on. For instance if you do bob = Person() and then bob.method2() , self will be the same object as bob . When you do self.attr1 = 'attr1' , you set the attribute on that object. If you then call method1 , it has access to all the attributes on the object. Any attributes you don't put there aren't there.

Simply put, if you never do self.attr1 = whatever , then trying to get the value of self.attr1 will never work. In your second example, you never do self.attr1 = ... , so there is no attribute attr1 to get.

I agree with zehnpaard that you are confusing things by using the same label attr1 as an attribute name ( self.attr1 ), a local variable name ( attr1 ), and a string value ( 'attr1' ). Change all of those to different things and you'll begin to see how they work differently.

In this:

class Person(object):
    def method1(self):
        print(self.attr1)

    def method2(self):
        self.attr1 = 'attr1'
        self.method1()

You have passed self into method1 function which stands for an instance of Person class. After that, you can invoke attr1 since you already have instance in method1 namespace.

That's why you don't have to pass string 'attr1' to method1 again to print.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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