How to Inherit an attribute from another class without using subclass

  • Python
  • Thread starter Arman777
  • Start date
  • Tags
    Class
In summary, The "Admin Class" has the following privileges:-The ability to ban users-The ability to show user privileges
  • #1
Arman777
Insights Author
Gold Member
2,168
193
I am pretty new to OOP in python, and just for fun, I have created a program that distincts an admin from the user.

Python:
 class User():
        def __init__(self, first_name, last_name, gender, age, country):
            """
            Description of the user
            """
            self.first_name = first_name
            self.last_name = last_name
            self.gender = gender
            self.age = age
            self.country = country
            self.login_attempts = 0
            self.admin = Admin(privileges='')

        def describe_user(self):
            """
            Printing the users information, if the user is admin do not give any information
            """
            if self.first_name == "Arman" and self.last_name == "Cam":
                print("This information is classified")
            else:
                print("First Name: ", self.first_name)
                print("Last Name:", self.last_name)
                print("Gender:", self.gender)
                print("Age:", self.age)
                print("Country:", self.country)

        def greet_user(self):
            """
            Greeting the users
            """
            if self.first_name == "Arman" and self.last_name == "Cam":
                print("Hello Admin!\nWelcome to the AQT Server")
            else:
                print("Hello", self.first_name, "!\nWelcome to the AQT Server\n")    class Admin():
        def __init__(self, privileges=''):
            self.privileges = privileges

        def show_privileges(self):
            """
            Showing the privileges of the admin
            """
            print(self.privileges)

        def add_privileges(self, new_privilege):
            """
            Adding a new privilege if needed
            """
            self.privileges += new_privilege    user1 = User("Arman", "Cam", "Male", 20, "Canada")
    user1.greet_user()
    user1.describe_user()
    user1.admin.add_privileges("ban user")
    user1.admin.show_privileges()
Now, I want to modify the `"show_privileges`" method in the `"Admin Class" such that

Python:
def show_privileges(self):
        """
        Showing the privileges of the admin
        """
        if self.first_name == "Arman" and self.last_name == "Cam":
            print(self.privileges)
        else:
            print("You have no privilege")

But in this case ofc the code gives me an error. Since "self.first_name`" is not defined in the ` "Admin" subclass.

In order to make things work I might create a subclass, but then I have to write something like

Code:
    user1 = Admin("Arman", "Cam", "Male", 20, "Canada")

Which I do now want. I want ` "Admin" ` to be an attribute in `"User` Class".

So, how can I add `self.first_name` in `Admin` class without using subclass method?

Also since User have lots of arguments, is there a shortcut syntax for passing all arguments of `User` in other functions?

Note: By subclass method I mean that `Admin(User)`
 
Technology news on Phys.org
  • #2
Arman777 said:
"self.first_name`" is not defined in the ` "Admin" subclass.

Admin is not a subclass; it doesn't inherit from User (because you said class Admin() instead of class Admin(User)). If it did inherit from User, you wouldn't have this problem.

Arman777 said:
I want ` "Admin" ` to be an attribute in `"User` Class".

Then you shouldn't be defining a separate Admin class. You should be adding a parameter to the constructor of the User class that says whether that particular user is an admin or not, and storing that in an instance attribute the same way you do with first_name and the other attributes.
 
  • #3
Arman777 said:
Also since User have lots of arguments, is there a shortcut syntax for passing all arguments of `User` in other functions?

Can you not just pass a User object to the function?
 
  • #4
I can think of a number of ways you could write this code, @PeterDonis has already indicated two, a third way is to pass a User object to the Admin constructor something like
Python:
class Admin():
  def __init__(self, user, privileges=''):
    self.user = user
    self.privileges = privileges
Then you can refer to an admin's first name in an Admin method as self.user.firstName.
 
  • Like
Likes jedishrfu and sysprog
  • #5
PeterDonis said:
Admin is not a subclass; it doesn't inherit from User (because you said class Admin() instead of class Admin(User)). If it did inherit from User, you wouldn't have this problem.
Then you shouldn't be defining a separate Admin class. You should be adding a parameter to the constructor of the User class that says whether that particular user is an admin or not, and storing that in an instance attribute the same way you do with first_name and the other attributes.
I have tried to create it as a subclass but it is not working well because I have to also adjust the self.admin = Admin() as well.
 
  • #6
pbuk said:
I can think of a number of ways you could write this code, @PeterDonis has already indicated two, a third way is to pass a User object to the Admin constructor something like
Python:
class Admin():
  def __init__(self, user, privileges=''):
    self.user = user
    self.privileges = privileges
Then you can refer to an admin's first name in an Admin method as self.user.firstName.
My code gives an error saying

TypeError: __init__() missing 1 required positional argument: 'user'

Which also occurs when I try to implement Admin as a subclass
 
  • #7
PeterDonis said:
hen you shouldn't be defining a separate Admin class.
I know how to do that. However, that's not the point. I am just trying to understand how to pass a attribute without defining a subclass
 
  • #8
Arman777 said:
I have tried to create it as a subclass but it is not working well because I have to also adjust the self.admin = Admin() as well.

I don't understand why you would have to do that.

Arman777 said:
I am just trying to understand how to pass a attribute without defining a subclass

"Pass an attribute" is very vague. So far, none of the things you have said you have tried even make sense.

Let's take a step back. What more general objective are you trying to accomplish with this code? For example, in what code might you use a User object vs. an Admin object?
 
  • Like
Likes Vanadium 50
  • #9
Arman777 said:
My code gives an error

We can't possibly tell why if you don't post your code.
 
  • Like
Likes Vanadium 50
  • #10
Arman777 said:
I have tried to create it as a subclass but it is not working well because I have to also adjust the self.admin = Admin() as well.

Here, also, it's impossible to tell why you are having problems if you don't post your code. Having Admin be a subclass of User is the most common way to do what it looks like you are trying to do, so if you're having problems with it, you're most likely not doing it correctly. But we can't help you fix that if we can't see your code.
 
  • #11
Arman777 said:
I have created a program that distincts an admin from the user.

That's not what your code posted in the OP is doing. Your code posted in the OP is assigning a new instance of the Admin class to the admin instance attribute of each new instance of the User class. Since each new instance of the Admin class has exactly the same attributes, it's impossible to use that to distinguish between admin and non-admin users, so your code is not doing what you intend.

What it looks like you are trying to do is to distinguish admin users from other users by their names (i.e., users with particular names are admins, other users are not). The name is an attribute of the User class, so you don't need a separate Admin class to distinguish admin from non-admin users; you just need an attribute or property on each instance of the User class that says whether that user is an admin, based on their name (or whatever other criterion you want). One example of how to do this would be to add the following to your User class:

Python:
@property
def is_admin(self):
    return self.first_name == "Arman" and self.last_name == "Cam"

Then you can use this property in the show_privileges method of the User class, for example:

Python:
def show_privileges(self):
        """
        Showing the privileges of the admin
        """
        if self.is_admin:
            print(self.privileges)
        else:
            print("You have no privilege")

And for this to work, you would need to replace the line self.admin = Admin(privileges='') in the User class constructor with self.privileges = '' (or you could pass the privileges in as a parameter).
 
  • Like
Likes Dale, sysprog and pbuk
  • #12
Arman777 said:
My code gives an error saying TypeError: __init__() missing 1 required positional argument: 'user'
That is because the Admin constructor now has an additional argument so that you can pass it the user

Python:
arman = new User("Arman", "Cam", "male", 20, "Canada")
armanAdmin = new Admin(arman)

Arman777 said:
Which also occurs when I try to implement Admin as a subclass
Then you must be implementing it wrong.

I think it would be a good idea if you revised the basic principles of class inheritance in Python, this tutorial at Programiz is pretty good.
 
  • #13
pbuk said:
I think it would be a good idea if you revised the basic principles of class inheritance in Python

I think you mean "revisited" or "reviewed"?
 
  • #14
pbuk said:
I think it would be a good idea if you revised the basic principles of class inheritance in Python

PeterDonis said:
I think you mean "revisited" or "reviewed"?
This seems to be a difference between British English vs. American English. A Brit will say "revise" to mean the same thing as an American saying "review".
 
  • Like
  • Wow
Likes sysprog and pbuk
  • #15
Mark44 said:
This seems to be a difference between British English vs. American English. A Brit will say "revise" to mean the same thing as an American saying "review".

Interesting, I didn't know that.
 
  • Like
Likes sysprog
  • #16
PeterDonis said:
Interesting, I didn't know that.
Yes, and I didn't know that 'revise' did not have that meaning in the US! What noun do you have for the act of going over things already studied (we call it 'revision')?
 
  • Like
Likes sysprog
  • #17
pbuk said:
What noun do you have for the act of going over things already studied (we call it 'revision')?

"Review", as @Mark44 said, or "revisit", as I said in my earlier post.
 
  • Like
Likes sysprog
  • #18
Whenever I read that some member plans to "revise their previous exams" I know they are either British or have learned British English.

If I told my students that I was going to "revise" their grades, some of the better students would be up in arms.:smile:
 
  • Like
Likes sysprog
  • #19
pbuk said:
Yes, and I didn't know that 'revise' did not have that meaning in the US! What noun do you have for the act of going over things already studied (we call it 'revision')?
You used a verb, 'revise', and asked about a noun. We in the US use 'revised' to mean 'adjusted after review' however, we don't tend to say 'if you revised the basic principles' when we mean 'if you were to review the basic priciples' ##-## I didn't there isolate the difference between 'revise' and 'review', because you didn't say 'if you were to have revised', for which we could easily substitute 'if you were to have reviewed' ##-## the important difference between the two is that in the US, 'review' in many instances requires only reading, whereas 'revise' usually implies rewriting; we may call a writing about something a 'review', but saying that I have 'revised' my opinion normally means that I have changed my opinion ##-## not merely that I have re-read it.
 
Last edited:
  • #20
I can understand your concerns and yes it does not seem logical to separate Admin class from the User.

For instance I can do something like

Python:
class User():
    def __init__(self, first_name, last_name, gender, age, country):
        """
        Description of the user
        """
        self.first_name = first_name
        self.last_name = last_name
        self.gender = gender
        self.age = age
        self.country = country
        self.login_attempts = 0class Admin(User):
    def __init__(self, first_name, last_name, gender, age, country, privileges='ban user'):
        super().__init__(first_name, last_name, gender, age, country)
        self.privileges = privileges

    def show_privileges(self):
        """
        Showing the privileges of the admin
        """
        if self.first_name == "Arman" and self.last_name == "Cam":
            print(self.privileges)
        else:
            print("You have no privilege")user1 = Admin("Keane", "Cam", "Male", 20, "Canada")
user1.show_privileges()
user2 = Admin("Arman", "Cam", "Male", 20, "Canada")
user2.show_privileges()
But in this case, I have to write

Python:
user2 = Admin("Arman", "Cam", "Male", 20, "Canada")
user2.show_privileges()

And that is not what I want. So I want to access the same thing by typing

Python:
user2 = User("Arman", "Cam", "Male", 20, "Canada")
user2.admin.show_privileges()

As you can see, Admin is an attribute in User Class. So I asked how can I do that , by taking Admin as a separate class. In this case the only possible solution seems to be something like

Python:
class User():
    def __init__(self, first_name, last_name, gender, age, country):
        """
        Description of the user
        """
        self.first_name = first_name
        self.last_name = last_name
        self.gender = gender
        self.age = age
        self.country = country
        self.login_attempts = 0
       self.admin = Admin(first_name='', last_name='', gender='',
                           age='', country='', privileges='')class Admin():
    def __init__(self, first_name, last_name, gender, age, country, privileges='ban user'):
        User.__init__(first_name, last_name, gender, age, country)
        self.privileges = privileges

    def show_privileges(self):
        """
        Showing the privileges of the admin
        """
        if self.first_name == "Arman" and self.last_name == "Cam":
            print(self.privileges)
        else:
            print("You have no privilege")user2 = User("Arman", "Cam", "Male", 20, "Canada")
user2.admin.show_privileges()

But it is not working.
 
  • #21
Please be more specific regarding what you mean by "But it is not working".
 
  • #22
Never mind ...
sysprog said:
Please be more specific regarding what you mean by "But it is not working".
Well most of the things are wrong actually. That was just for me trying things...Line 18 does not make much sense unless you want to use subclass method. I am just asking in general. If you have an attribute in one class, and you want to use it in another class, can you do it without using the subclass .
 
  • #23
I think that "most of the things are wrong" is not in itself a useful remark for diagnostic purposes. Your question, "If you have an attribute in one class, and you want to use it in another class, can you do it without using the subclass", I interpret as meaning 'a subclass', not "the subclass", as "the subclass" implies that there is already 'a subclass' that we are discussing, which here there is not. A class attribute, if not defined as global, is local to the class.
 
Last edited:
  • #24
sysprog said:
I think that "most of the things are wrong" is not in itself a useful remark for diagnostic purposes. Your question, "If you have an attribute in one class, and you want to use it in another class, can you do it without using the subclass", I interpret as meaning 'a subclass', not "the subclass", as "the subclass" implies that there is already 'a subclass' that we are discussing, which here there is not. A class attribute, if not defined as global, is local to the class.
Let me use "child-class".

If I define a child-class of User() as Admin() , I can use the attributes of the User() in the Admin().

However, I was trying to know that can you still use the attributes of the User() in Admin() without making Admin a child-class of user (i.e Admin(User)).

If the answer is "no". That is fine by me.

Admin- User classes are just an example. You can call them X Y etc.
 
  • #25
Arman777 said:
Let me use "child-class".

If I define a child-class of User() as Admin() , I can use the attributes of the User() in the Admin().

However, I was trying to know that can you still use the attributes of the User() in Admin() without making Admin a child-class of user (i.e Admin(User)).

If the answer is "no". That is fine by me.

Admin- User classes are just an example. You can call them X Y etc.
You haven't said what alternative definition you propose for Admin(), if it's not to be a subclass of User() ##-## it can't inherit attributes as a child class from a parent class if it's not a child class of that parent class.
 
  • #26
sysprog said:
You haven't said what alternative definition you propose for Admin(), if it's not to be a subclass of User() ##-## it can't inherit attributes as a child class from a parent class if it's not a child class of that parent class.
I see, okay then thanks

By alternative was to use something like
Python:
self.admin = Admin(first_name='', last_name='', gender='',
                           age='', country='', privileges='')

Post 20, Line 12 in second code
 
  • #27
Arman777 said:
I see, okay then thanks

By alternative was to use something like
Python:
self.admin = Admin(first_name='', last_name='', gender='',
                           age='', country='', privileges='')

Post 20, Line 12 in second code
That looks like you want to give adminstrative privileges over oneself, without thereby giving administrative privileges over others ##-## that seems to me to be a reasonable thing to want to do ##-## but perhaps using class attributes isn't how you should implement that ##-## maybe you should use an if statement . . .
 
  • #28
Python:
class User():
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name
        self.admin = Admin()class Admin():
    def __init__(self, privileges='ban user'):
        self.privileges = privileges

    def show_privileges(self):
        print(self.privileges)user2 = User("Arman", "Cam")
user2.admin.show_privileges()

Will print

Python:
ban user

My question is how can you make self.firt_name work under Admin(), without making Admin() a child class of User() (also without moving the methods of Admin() into User() )

Or is something like this possible ?

Python:
class User():
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name
        self.admin = Admin()class Admin():
    def __init__(self, privileges='ban user'):
        self.privileges = privileges

    def show_privileges(self):
        if self.first_name == "Arman":
            print(self.privileges)
        else:
            print("You don't have privileges")user2 = User("Arman", "Cam")
user2.admin.show_privileges()
 
  • #29
I don't quite understand the 'ban user' privilege ##-## and, in your most recent code in this thread, it looks to me like you've re-initialized 'self' without including 'self.first_name', so that your subsequent reference to 'self.first_name' will be undefined ##-## I think that, no, that won't work.
 
Last edited:
  • #30
Arman777 said:
My question is how can you make self.firt_name work under Admin(), without making Admin() a child class of User()
You can't: first_name is a property of a User object not an Admin object. What you can do as I highlighted previously is make a user a property of an Admin object, then you can use self.user.first_name in an Admin object.

Arman777 said:
(also without moving the methods of Admin() into User() )
There is never any need to move methods that are only relevant to Admin objects into the User class, whether Admin is a subclass of User or an unrelated class.

Arman777 said:
Or is something like this possible ?
Python:
class User():
...

Yes this is possible, again I suggested how above but I will spell it out explicitly below. But beware that just because this is possible doesn't mean its a good idea: are you familiar with the concept of an 'anti-pattern'?

Python:
class User():
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name
        self.admin = Admin(self)

class Admin():
    def __init__(self, user, privileges='ban user'):
        self.user = user
        self.privileges = privileges

    def show_privileges(self):
        if self.user.first_name == "Arman":
            print(self.privileges)
        else:
            print("You don't have privileges")

user2 = User("Arman", "Cam")
user2.admin.show_privileges()
 
  • Like
Likes sysprog and Arman777
  • #31
pbuk said:
But beware that just because this is possible doesn't mean its a good idea:
Yeah it seems a bit awkward.. But yes this is what I was looking for.

pbuk said:
are you familiar with the concept of an 'anti-pattern'?
Nope, never heard.
pbuk said:
You can't: first_name is a property of a User object not an Admin object. What you can do as I highlighted previously is make a user a property of an Admin object, then you can use self.user.first_name in an Admin object.
I tried that but it did not worked that time, maybe I did something wrong. But this time it works
 
  • #32
It seems that anti-pattern is a bad idea to solve/design a problem
 
  • Like
Likes pbuk
  • #33
Python:
class User():
    def __init__(self, first_name, last_name, gender, age, country):
        """
        Description of the user
        """
        self.first_name = first_name
        self.last_name = last_name
        self.gender = gender
        self.age = age
        self.country = country
        self.login_attempts = 0

    def describe_user(self):
        """
        Printing the users information, if the user is admin do not give any information
        """
        if self.first_name == "Arman" and self.last_name == "Cam":
            print("This information is classified")
        else:
            print("First Name: ", self.first_name)
            print("Last Name:", self.last_name)
            print("Gender:", self.gender)
            print("Age:", self.age)
            print("Country:", self.country)

    def greet_user(self):
        """
        Greeting the users
        """
        if self.first_name == "Arman" and self.last_name == "Cam":
            print("Hello Admin!\nWelcome to the AQT Server")
        else:
            print("Hello", self.first_name, "!\nWelcome to the AQT Server\n")

    def increment_login_attempts(self):
        '''
        Increment the login attempts one by one, each time users try to enter
        '''
        self.login_attempts += 1
        print("You have tried logging in", self.login_attempts, "times")

    def reset_login_attempts(self):  # method
        '''
        Resetting the logging attempts
        '''
        self.login_attempts = 0
        print("Login Attempt has set to ", self.login_attempts)class Admin(User):
    def __init__(self, first_name, last_name, gender, age, country, privileges=''):
        super().__init__(first_name, last_name, gender, age, country)
        self.privileges = privileges

    def show_privileges(self):
        """
        Showing the privileges of the admin
        """
        if self.first_name == "Arman" and self.last_name == "Cam":
            print(self.privileges)
        else:
            print("You have no privileges!")

    def add_privileges(self, new_privilege):
        """
        Adding a new privilege if needed
        """
        if self.first_name == "Arman" and self.last_name == "Cam":
            self.privileges += new_privilege
        else:
            print("You can not add any privilege!")user1 = User("Keane", "Cam", "Male", 20, "Canada")
user2 = Admin("Keane", "Cam", "Male", 23, "USA")

user1.greet_user()
user1.describe_user()

user2.greet_user()
user2.describe_user()
user2.add_privileges("Ban User")
user2.show_privileges()

I guess this is the best way to implement
 
  • #34
Arman777 said:
Let me use "child-class".

You don't need to make up a new term. The term "subclass" describes this.

Arman777 said:
I was trying to know that can you still use the attributes of the User() in Admin() without making Admin a child-class of user (i.e Admin(User)).

If the answer is "no". That is fine by me.

The answer is no. See my post #11 for a description of a better way to do what it looks like you are trying to do.
 
  • #35
Arman777 said:
I guess this is the best way to implement

You have the basic idea of how you would make Admin a subclass of User, but your implementation of this still has some issues:

(1) If every admin is described by an instance of the Admin class, then why are you checking the first and last name in the show_privileges method? If a user is not an admin, you won't use the Admin class to describe them.

(2) It makes no sense to have an instance of User and an instance of Admin for the same user, which is what your user1 and user2 code appears to be doing (unless the first name of user2 is a typo and should be "Arman"). Either a user is an admin or they aren't. If they are, you create an instance of Admin for them. If they aren't, you create an instance of User for them.

(3) If you want to be able to call show_privileges and add_privileges on any user, without having to know whether they are admins or not, then you need to have show_privileges and add_privileges methods in the User class, and then override them in the Admin class. Something like this:

Python:
# in class User:

    def show_privileges(self):
        print("You have no privileges!")

    def add_privileges(self, new_privilege):
        print("You can not add any privilege!")

# in class Admin(User):

    def show_privileges(self):
        print(self.privileges)

    def add_privileges(self, new_privilege):
        self.privileges += new_privilege

Then you would create the two instances like so:

Python:
user1 = User("Keane", "Cam", "Male", 20, "Canada")
user2 = Admin("Arman", "Cam", "Male", 23, "USA")

Note that it's up to the code creating the instances to decide whether to create an instance of the User class or the Admin class for each user.
 
  • Like
Likes pbuk

Similar threads

  • Programming and Computer Science
Replies
9
Views
906
Back
Top