2

I can access class-level attribute of a class (B) in method of another class (A) but I cannot access that at class-level of class A. The issue can be resolved by defining B after A but why is this so and how can I access that keeping class B after class A.

I am looking for solution without class inheritance and without creating object of class B inside __init__ of class A.

See the code here:

class A:
    a=B.b # This doesn't work
    def __init__(self):
        print(B.b) #This works
class B:
    b=[1,2,3]
martineau
  • 119,623
  • 25
  • 170
  • 301
ahsan naeem
  • 245
  • 2
  • 9
  • Try defining the classes in the opposite order. – alani Jun 20 '20 at 21:48
  • The `a=B.b` is executed when the class is defined, and `B` does not yet exist. The code inside `__init__` is only run when the class is instantiated. – alani Jun 20 '20 at 21:49
  • 1
    @alaniwi Yes I said that it can be solved like that but why not with this order? – ahsan naeem Jun 20 '20 at 21:49
  • 1
    By the time you try to actually run `A.__init__`, `B.b` exists. That's not the case for your attempt to set `a=B.b`. – user2357112 Jun 20 '20 at 21:50
  • If you really need to define class `A` first, then you are going to have to put the list into another module-level variable before `A` is defined, and then inside `class B` you can set `b` equal to the value in that variable. – alani Jun 20 '20 at 21:51
  • 1
    @user2357112supportsMonica Yes I got the answer of Why... Thanks – ahsan naeem Jun 20 '20 at 21:53
  • @ahsannaeem What is your use case? – alani Jun 20 '20 at 21:54
  • 1
    @alaniwi Can you plz give example code? – ahsan naeem Jun 20 '20 at 21:57
  • 1
    @alaniwi The exact use case is that lower class is a `Student` class having a class-level attribute `allStudents` which is a list. Whenever a student object is created, it is inserted into that list inside `__init__` method. Now the upper class is `Department` where I want to access this `allStudent` list. – ahsan naeem Jun 20 '20 at 22:02
  • 1
    That kind of global instance registry managed in `__init__` is a typical bad design new programmers come up with because they're unfamiliar or uncomfortable with better designs. Keeping track of instances shouldn't be handled by `__init__` - `__init__` usually doesn't have enough information to do a good job of that, and it complicates things like discarding instances. – user2357112 Jun 20 '20 at 23:11

1 Answers1

1

Assuming you don’t need to use the attribute while defining A (e.g., for a default argument), you can just assign it later:

class A:
    def __init__(self):
        print(B.b)
class B:
    b=[1,2,3]
A.a=B.b

or even

class A:
    def __init__(self):
        print(B.b)
class B:
    A.a=b=[1,2,3]

if you consider the classes so closely related that an assignment to one inside the other is less surprising than one outside both.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76