Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 months ago.
Improve this question
I came by a code and wanted to get more understanding on when to use such arrangement.
What would be a good scenario of not using __init__'s argument (name) in self?
class ArgumentNotUsedInSelf:
def __init__(self, name: str):
self.type = "user"
user_one = ArgumentNotUsedInSelf("Mike")
print(user_one.type)
Any explanations from architectural (and not only) point of view are most welcome!
Some of the reasons for this can be:
Historical. The class used to use the argument, but it was changed so it's no longer meaningful. The argument was kept for backward compatibility.
Class hierarchy. This may be a child class of a class that uses the argument, but the child overrides the need for it. The argument is required for compatibility with the parent.
Sort of Barmar's historical example... let's say:
ArgumentNotUsedInSelf used to do something with name, but now doesn't.
But name is still used in SubClass, and changing everything could mess up dependent programs.
class ArgumentNotUsedInSelf:
def __init__(self, name: str):
self.type = "user"
class SubClass(ArgumentNotUsedInSelf):
def __init__(self, name):
super(SubClass, self).__init__(name)
self.name = name
x = SubClass('Mike')
print(x.name, x.type)
Output:
Mike user
This would be helpful if you want to store the field "name" of the created object and re-use it later:
class ArgumentNotUsedInSelf:
def __init__(self, name: str):
self.type = "user"
self.name = name
user_one = ArgumentNotUsedInSelf("Mike")
print(user_one.type)
print(user_one.name)
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 months ago.
Improve this question
I'm wondering whether it is a valid use case of functools.partial to partially initialize object attributes in python. Let's say I have some base class A that has three object-level attributes (attr1, attr2, attr3):
class A:
def __init__(self, attr1, attr2, attr3):
self.attr1 = attr1
self.attr2 = attr2
self.attr3 = attr3
def do_something(self):
pass
Now I want to create objects based on this base class for which one of the attributes (say attr1) is always fixed, but the other two may vary. One way I can think of doing this is to define a class that inherits from base class A and has a fixed class-level attribute which is used during initialization, something like this:
class PartialA(A):
attr1="foo" # fixed class-level attribute
def __init__(self, attr2, attr3):
super().__init__(self.attr1, attr2, attr3)
I can then create objects by specifying only the varying object-level attributes, like so:
partial_a = PartialA(attr2="baz", attr3="baz")
Another way to achieve a similar behavior would be to use functools.partial to partially initialize the __init__ of the base class A and then create objects off of it:
from functools import partial
PartialA = partial(A, attr1="foo")
partial_a = PartialA(attr2="bar", attr3="baz")
Are both approaches equally valid, or are there dangers/drawbacks to the approach using functools.partial in this way that I am currently not aware of? Would be happy to hear your opinions!
I tried both of the approaches outlined above and so far, I can not really see any difference in terms of behavior. But there might well be some reasons to favor one over another that I'm currently unaware of.
In both cases, you are basically defining factory functions to create instances of A. I would take a third route, an alternate constructor implemented using a class method.
class A:
def __init__(self, attr1, attr2, attr3):
self.attr1 = attr1
self.attr2 = attr2
self.attr3 = attr3
#classmethod
def with_foo(cls, attr2, attr3):
return cls("foo", attr2, attr3)
def do_something(self):
pass
a = A.with_foo("bar", "baz") # a = A("foo", "bar", "baz")
One major difference between this and your two attempts is that you can't override how A.with_foo sets the first attribute. (With the class, you can simply redefine PartialA.attr1 before creating an instance, plus you now have a weird second class that doesn't need to exist. With partial, you can still pass your own value of attr1 as a keyword argument.)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
Can somebody please explain what is the purpose of 'object' and 'list' parameters in the classes Card and StandardDeck? I find little information about this.
Phycharm says this about 'object' in class Card():
The base class of the class hierarchy.
When called, it accepts no arguments and returns a new featureless instance that has no instance attributes and cannot be given any.
Is class card considered base class because of the 'object' parameter? Does the super().__init__() from class StandardDeck inherited from class Card? I really hope someone can give a good explanation i have been struggling for hours.
def main():
class Card(object):
def __init__(self, value, suit):
self.value = value
self.suit = suit
class StandardDeck(list):
def __init__(self):
super().__init__()
suits = list(range(4))
values = list(range(13))
[[self.append(Card(i, j)) for j in suits] for i in values]
deck = StandardDeck()
for card in deck:
print(card)
main()
object is the base class (also referred to a super class) for the derived class Card. This means Card inherit all the functionality and state of the base class (and as others said already this is implied anyhow), and it allows Card to override (or change) methods as needed. Another way to say that is Card is a more specialized class than object.
Similarly, list is the base class for StandardDeck.
I would also add that it's not a particular good design. For instance, list has a method called clear(). What does it mean to clear() a StandardDeck? It would be better design to use whatever data structures are needed an implementation detail (instance variables). This is sometimes expressed as failing the Liskov substitution principle (LSP).
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
This post was edited and submitted for review 23 days ago.
Improve this question
I recently stumbled upon a problem, How do i access a class's instance variables (aka the variables inside __init__) from outside/inside the file without creating an instance of a class (i.e main = main.foo()).
Example:
class foo:
def __init__(self,name):
self.name = name
class bar:
os.mkdir(foo.name)
you can set the variable as global, and then you will be able to access this variable from everywhere. and also modifying it.
Not sure why you are using nested classes, but:
foo_name = None
class main:
class foo:
def __init__(self,name):
global foo_name
foo_name = self.name = name
class bar:
def __init__(self):
print(foo_name)
main.foo("Jonathan")
main.bar()
Prints out "Jonathan"
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I took working example code and tried to add another variable self.species = martian under the init method. Seems you cannot do this which doesn't make sense to me.
# A Sample class with init method
class Person:
# init method or constructor
def __init__(self, name, species):
self.name = name
self.species = martian
# Sample Method
def say_hi(self, name, species):
print('Hello, my name is', self.name)
print('I am', self.species)
p = Person('Martin')
p.say_hi()
TypeError: __init__() missing 1 required positional argument: 'species'
When creating the person p you need to pass the species parameter. As well, you are not using that argument in your function.
Calling could look like this:
p = Person("Martin", "martian")
Then within the constructor you reference the argument like this:
self.species = species
this is how your code should look like.
# A Sample class with init method
class Person:
# init method or constructor
def __init__(self, name, species):
self.name = name
self.species = species
# Sample Method
def say_hi(self):
print('Hello, my name is', self.name)
print('I am', self.species)
p = Person('Martin', 'martian')
p.say_hi()
I suggest you watch some other beginner's video lectures on 'init' method and 'Object oriented programming in python' before writing these type of codes otherwise it would be very hard to understand beyond this point
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I am practicing python classes. I got that classes variables are shared among all the instances, while instance variables belongs to each object, and thus need to be defined for each instance. In the following classes, in reference to the variable raise_amount, if I write the last code line like that: self.pay = int(self.pay * Employee.raise_amount), the behavior is the same.
What is the difference between the two cases, if any?
class Employee:
raise_amount = 1.04
def __init__(self ,first ,last ,pay ):
self.first = first
self.last = last
self.pay = pay
self.email = first+"."+last+"#company.com"
def apply_raise(self): #but this is not an attribute
self.pay = int(self.pay * self.raise_amount)
#or self.pay = int(self.pay * Employee.raise_amount)
I assume your are referring to the self.raise_amount. In the case where you have it as that python must first look for instance variable and if not found it looks for similarly named class variable and creates a copy of it as an instance variable and uses that. if you were to then change the self.raise amount it would only be for the instance and not for any other instance made from the class.
Try creating an instance of the class and use the apply_raise method on it. then try changing the raise_amount class variable to something like 2.0 and call the method on the instance again. what you should see is that the amount only goes up 1.04 times, not 2. that is because it used the instance value it created the first time you ran the method.
Note: original post was edited to change to use the Class name for the raise amount. This post was a reply while it was self.raise_amount.
The lookup for the expression self.raise_amount can be complicated in general, be we can simplify it knowing that there are no methods or descriptors involved.
If self has an instance attribute named raise_amount, the value of that attribute is returned.
Otherwise, we start looking for class attributes, starting with the immediate type of self, here Employee. Since Employee.raise_amount is defined, we get that value...
... but what if Employee.raise_amount hadn't been defined? We would have moved on to the next class in the method resolution order of Employee, namely object. Since object.raise_amount is not defined, an AttributeError would have been raised.