Python Object inheritance - python

class Phone:
def install():
...
class InstagramApp(Phone):
...
def install_app(phone: "Phone", app_name):
phone.install(app_name)
app = InstagramApp()
install_app(app, 'instagram') # <--- is that OK ?
install_app gets a Phone object.
will it work with with InstagramApp object ?

The inheritance works correctly. install method is inherited from Phone class. But your code doesn't work. When you run it, it will say:
TypeError: Phone.install() takes 0 positional arguments but 2 were given
What are these two arguments that have been passed?
Second one is obviously the 'instagram' string. You passed that but no parameter expects it.
The first one is, Because you invoke that install() method from an instance, Python turns it into a "Method" and automatically fills the first parameter of it to a reference to the instance(this is how descriptors work). But again you don't have any parameter to receive it.
To make that work:
class Phone:
def install(self, name):
print(self)
print(name)
class InstagramApp(Phone):
...
def install_app(phone: "Phone", app_name):
phone.install(app_name)
app = InstagramApp()
install_app(app, "instagram")

Yes, methods are also inherited from classes. However, you will need to add a parameter to the install method so it can take the app name:
class Phone:
def install(self, app_name): # Allow the method to take an input app name
...
class InstagramApp(Phone):
...
def install_app(phone: "Phone", app_name):
phone.install(app_name)
app = InstagramApp()
install_app(app, 'instagram') # Yes, this will also work with the InstagramApp class

Yes - so long as the InstagramApp doesn't delete any of the methods that 'install_app', and the methods return the same types as the Phone class does then it will work.
I am curious as to why to pass the instance and pass the name as text - you could accomplish the sanme by simply ascessing the __name__ variable of the class - so for instance :
`app.__class_.__name__ will equal 'Instagram'
As others have pointed out you need to fix the various function calls.

install_app gets a Phone object. will it work with InstagramApp object?
the inheritance class will have the function
class Phone:
def install(app_name:str):# change type to str
pass
class InstagramApp(Phone):
pass
def install_app(phone: Phone, app_name):# change the type to Phone Class
phone.install(app_name)
app = InstagramApp()
install_app(app, 'instagram') #

Related

Passing python class object to bottle template

My class looks like this:
class Person:
def __init__(name=None, id_=None):
self.name = name
self.id_ = id_
# I'm currently doing this. member object is of Person type.
return template('index.html', name=member.name, id_=member.id_)
# What I want to do
return template('index.html', member=member)
First way is fine when we don't have many attributes to deal, but my class currently has around 10 attributes and it doesn't look good to pass so many parameters to template function. Now I want to pass an object of this class to bottle template and use it there. How can I do it?
# What I want to do
return template('index.html', member=member)
Just do that. It should work fine. In your template, you'll simply reference member.name, member.id_, etc.
If you have python 3.7+
from dataclasses import dataclass, asdict
#dataclass
class Person:
name: str
id_: str
member = Person('toto', '1')
return template('index.html', **asdict(member))
But maybe its more interesting to inject your object directly in your template.

passing data from one class method to another class method

I am learning Python and classes and i encountered a challenge that i need help with.
When I try to pass data from one class method to another class method i run into an error that tells me it misses a positional argument
example:
class Student:
def __init__(self, name):
self.name = name
def pass_to_dl(self):
DataLayer.Datalayer.create_dict_entry(self.name)
class Datalayer:
def __init__(self):
self.dict = {}
def create_dict_entry(self, name):
new_name = {"name":name}
self.dict.update(new_name)
new_student = Student("some_name")
The error I get is:
TypeError: create_new_student() missing 1 required positional argument:
i assume it is because create_dict_entry expects two arguments and I am sending only one
now i can overcome this if i do two things
make the create_dict_entry in DataLayer static
move the dict outside of the DataLayer class
but truthfully that does not seem like the right approach to me i think
i would love to hear your view on this matter
thnx
ps. i dont want student to inherit from DataLayer as i consider DataLayer a non related class that just holds data that i acquire form classes such as Student, Teacher etc
Not sure it's the way you want to go, but if I understand correctly what you're trying to do, I think you want to use inheritance.
class Datalayer:
def __init__(self):
self.dict = {}
def create_dict_entry(self, name):
new_name = {"name":name}
self.dict[self.name] = new_name
class Student(Datalayer):
def __init__(self, name):
super().__init__()
self.name = name
def pass_to_dl(self):
self.create_dict_entry(self.name)
So in this example, Student is your "child class" (that's why you pass Datalayer as its argument). In your __init__, you want to call super(Student, self).__init__() (or just super().__init__() to instantiate your "parent class", Datalayer so you can access trigger its __init__ function.
You may want to read some other examples to understand it properly (https://realpython.com/python-super/).

Use outer class instance as self in inner class?

I'm writing a wrapper for the GMAIL API. In this wrapper, I am trying to include subattributes in the "main class" so it more closely follows the below:
Previously, I was use methods such as:
class Foo:
def __init__(self, ...):
# add some attributes
def get_method(self, ...):
return some_stuff
This allows me to do foo.get_method(...). To follow the GMAIL API, I try to do:
class Foo:
def __init__(self, ...):
# add some attributes
#property
def method(self):
class _Method:
#staticmethod
def get(self, ...):
return some_stuff
return _Method()
Which allows me to do foo.method.get(...). The above has some problems, it redefines the class every time, and I have to add #staticmethod above every method as part of it. I do realise that I could create the class at the outer class level, and set a hidden variable for each which then .method returns or creates, but this seems like too much workaround.
tldr: Is it possible to make the instance passed to the inner class as self be the instance of the outer class (I do not wish to have to pass the attributes of the outer class to each inner class).
Instead of sharing the self parameter between classes, you are probably better off just passing the things you need to the constructor of the class you instantiate.
class Messages:
def __init__(self, name):
self.name = name
def method(self, other_arg):
return self.name + other_arg
class Test:
name = "hi"
def __init__(self):
self.messages = Messages(name=self.name)
If you need to pass a lot of information to the constructor and it starts becoming unwieldy, you can do something like split the shared code into a third class, and then pass that between the Test and Messages classes as a single object.
In Python there are all sorts of clever things that you can do with metaclasses and magic methods, but in 99% of cases just refactoring things into different classes and functions will get you more readable and maintainable code.
Users should have an instance of messages, which allows method get. The scetch for code is:
class Messages:
...
def get()
...
class Users:
...
messages = Messages(...)
allows
users = Users()
users.messages.get()
The bad thing in this API is plural names, which is a bad sign for class. If done from scratch you would rather have classes User and Message, which make more sense.
If you have a closer look at GET/POST calls in the API you link provided, you would notice the urls are like UserId/settings, another hint to implement User class, not Users.
self in the methods reference the self of the outer class
maybe this is what you want factory-method
Although the example code I'll provide bellow might be similar to the already provided answers, and the link above to another answer might satify you wish, because it is slight different formed I'll still provide my vision on what you asked. The code is self explanatory.
class User:
def __init__(self, pk, name):
self.pk = pk
self.name = name
self._messages = None
def messages(self):
if self.messages is None:
self._messages = Messages(self.pk)
return self._messages
class Messages:
def __init__(self, usr):
self.usr = usr
def get(self):
return self._grab_data()
def _grab_data(self):
# grab the data from DB
if self.usr == 1:
print('All messages of usr 1')
elif self.usr == 2:
print('All messages of usr 2')
elif self.usr == 3:
print('All messages of usr 3')
one = User(1, 'One')
two = User(2, 'Two')
three = User(3, 'Three')
one.messages().get()
two.messages().get()
three.messages().get()
The messages method approach practical would be the same for labels, history etc.
Edit: I'll give one more try to myself trying to understand what you want to achieve, even though you said that
I have tried numerous things with defining the classes outside of the container class [...]
. I don't know if you tried inheritance, since your inner class me, despite it quite don't represent nothing here, but still looks like you want to make use of its functionality somehow. You said as well
self in the methods reference the self of the outer class
This sounds to me like you want inheritance at the end.
Then the way to go would be (a proximity idea by using inheritance):
class me(object):
def __init__(self):
self.__other_arg = None # private and hidden variable
# setter and getter methods
def set_other_arg(self, new_other_arg):
self.__other_arg = new_other_arg
def get_other_arg(self):
return self.__other_arg
class Test(me):
name = 'Class Test'
#property
def message(self):
other_arg = self.get_other_arg()
if other_arg is not None:
return '{} {}'.format(self.name, other_arg)
else:
return self.name
t = Test()
t.set_other_arg('said Hello')
print(t.message)
# output >>> Class Test said Hello
I think this could be a preferable way to go rather than your inner class approach, my opinion, you'll decide. Just one side note, look up for getter and setter in python, it might help you if you want to stick with the inheritance idea given.

Python class with static method and reference to self

I have a class where I want to reference self from within a static method. Is there a way to do this?
class User(object):
email = "username"
password = "********"
#staticmethod
def all():
return {"ex": self.password}
print(User.all())
The way to do this is with a classmethod instead. The way this works is that the first argument is the class itself, which you can access your variables using the dot operator.
For example:
class User(object):
email = "username"
password = "********"
#classmethod
def all(cls):
return {"ex": cls.password}
print(User.all())
https://docs.python.org/2/library/functions.html#classmethod
No, there isn't.
The point of a staticmethod is that it does not need either instance (self) nor class (typically called cls) information to do its job.
If your staticmethod needs self then it isn't a staticmethod and you should just define it normally.

Issue in calling the base class methods

I am newbie in Python.I know this question is useless.But I am frustrated with my issue.I have 2 methods defined in my base class Animals.When I try to call the base methods in my inherited classes it shows these error:
NameError: name 'display_name' is not defined
class Animals():
def display_name(self):
print ('Name is Mr.X')
def display_age(self):
print('Age is 25')
class Name(Animals):
display_name(self)
class Age(Animals):
display_age(self)
n=Name()
a=Age()
n.display_name()
a.display_age()
You need to refer to the display_name function with a self prefix instead of passing self as an argument.
Also, as noted by Antimony, you need to call the display_name from within a function that is associated with an instance of the class (inside a function that accepts the self argument).
Code that appears outside a method function but inside a class is associated with the whole class, not with any particular instance of that class - using the self variable in this context has no meaning - if you create multiple objects from the class which one does it refer to?
class Animals():
def display_name(self):
print ('Name is Mr.X')
def display_age(self):
print('Age is 25')
class Name(Animals):
def call_display_name(self):
self.display_name()
class Age(Animals):
def call_display_name(self):
self.display_age()
Name().call_display_name()

Categories