0

I am new to Python and didn't find an answer to the following problem: I have two classes and want them to use variables from each other. Is there a simple way to do this because if I do it like this class a does not know that class b exists.

class a:
    y=1
    print(b.x)

class b:
    x=1
    print(a.y)

And how do I use overwrite the variables, the following code does not work:

class a:
    y=b.x

class b:
    x=1
martineau
  • 119,623
  • 25
  • 170
  • 301
Lukas
  • 1
  • 1
  • 1
    You can use variable from the other class, but the way you used `print` is wrong. The class does not directly handle `print`, put it inside a function and then call that function instead. – Rocky Li Mar 13 '19 at 18:04
  • How do I use variables from other classes? I am getting the NameError: name 'b' is not defined – Lukas Mar 13 '19 at 18:30
  • In your latter case, define `b` first. – Rocky Li Mar 13 '19 at 18:31
  • 1
    You're not really using classes in an effective manner (i.e. as though they were variables holding a single values). Generally speaking they should be thought-of and used as code templates without specific values assigned to as class attributes, but the instances of them using the `self` argument passed to all methods of the class. – martineau Mar 13 '19 at 18:33
  • But if I had 3 classes with different variables lets say Class A has variable a, Class B has variable b and Class C has variable c. Now I want to put a into B, b into C and C into a there would be no possibility? – Lukas Mar 13 '19 at 18:51

3 Answers3

2

You are executing print as part of the class definition. It executes as soon as python sees that line of code, before it's read the part about class b.

Instead, use functions inside the classes to execute code after the classes have been defined:

class a:
    y=1
    def go():
        print(b.x)

class b:
    x=1
    def go():
        print(a.y)

a.go()
b.go()
Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
1

As I said in a comment, your code isn't making effective use of classes. Here's what I think would be better approach that offers more flexibility in working around the circular reference issue.

First the class definitions (which follow the PEP 8 naming convention guidelines):

class A:
    def __init__(self, value, linked_value=None):
        self.y = value
        if isinstance(linked_value, B):
            self.linked_value = linked_value.x

    def print_linked_value(self):
        print(self.linked_value)


class B:
    def __init__(self, value, linked_value=None):
        self.x = value
        if isinstance(linked_value, A):
            self.linked_value = linked_value.y

    def print_linked_value(self):
        print(self.linked_value)

Definitions like that provide two ways to set up the circular references:

  1. By creating them separately, then explicitly linking them:

    # First create instances of each class.
    a = A(1)
    b = B(42)
    
    # Then link them.
    a.linked_value = b.x
    b.linked_value = a.y
    
    a.print_linked_value()  # -> 42
    b.print_linked_value()  # -> 1
    
  2. *OR* by creating the first one without a linked value and leaving only the second needing to be linked manually.

    # First create instances of each class, but link the second to the first
    # when it's created.
    a = A(1)
    b = B(42, a)  # Create and link to first.
    
    # Then link the first to the second to complete the circular references.
    a.linked_value = b.x
    
    # Same result.
    a.print_linked_value()  # -> 42
    b.print_linked_value()  # -> 1
    

Final note: Another, more advanced alternative that can also be applied in situations like this by using the built-in property() function as a decorator to create "descriptors". Here's an answer to a somewhat related question that illustrating its use.

martineau
  • 119,623
  • 25
  • 170
  • 301
0
class A:
    y = 1
    def foo(self):
        print B.x

class B:
    x = 1
    def bar(self):
        print A.y

>>> A().foo()
2
>>> B().bar()
1

Use 'print' in some function definition.

Ashish kulkarni
  • 644
  • 2
  • 7
  • 13