Confused about static class vars in python - python-3.x

Here a little example code:
class A:
staticvar=3;
def foo2(self):
print("------ Foo2")
print("static: "+str(A.staticvar));
print("instance: "+ str(self.staticvar));
class B(A):
def setStaticVar(self, num):
B.staticvar=num;
a=A();
b=B();
a.staticvar=7;
a.foo2();
b.setStaticVar(100);
a.foo2();
b.foo2();
what results in:
------
static: 3
instance: 7 -->correct. Instance var modified
------
static: 3
instance: 7 --> Not correct. Why static var is not 100
------
static: 3
instance: 100 --> Correct, but this value should be shared between A and B
Why is this happening? Shouldn't the static variable be shared between A and B? Why when it is modified in b through b.
From this example it seems, each class has its own static var (not really static from my point of view because there would only be one static var and we have 2, one per class).
Could anyone explain this behaviour?
Cheers.

I suspect what you're running into is an issue of name resolution. When you get B.staticvar, the interpreter fails to find it and falls back on its super classes to try to resolve the name. Upon traversing to A, the interpreter finds staticvar and returns the value.
When you set a value to B.staticvar, however, you get much the same behavior as your "instance" case, where a new property called staticvar is added to B. Now, when it attempts to resolve the property name on B (or instances thereof), it uses this new value without ever falling back to A. In Python, inheriting a class isn't much about sharing its properties, it's about setting a fallback class to resolve names when they aren't defined in your child class (hence why there's no need to explicitly "override" methods, and why you must remember to call super(A).method_name within B.method_name if you want the parent function to be run).
To get the behavior you're asking for, either define setStaticVar in A, and/or change its body to A.staticvar=num

Related

If I return a class instance inside a class function, it creates a new object or it returns the existing object associated to that data?

For example:
class DogOwners(object): def get_this_animal(id, dog_name): return Dog(id=id, name=dog_name)
Would this return a new object or the existing one associated to the *args of get_this_animal()?
It returns the data I want but I can't tell if now I have two dogs with the same data
Any time you run Dog(...), you're creating a new object (assuming you didn't do anything special to the class to change that fact). Calling a class as a function constructs a new instance by default. You can also check this yourself using id:
# I added the necessary 'self' parameter, and changed the 'id' parameter
def get_this_animal(self, dog_id, dog_name):
new_dog = Dog(id=dog_id, name=dog_name)
print(id(self), id(new_dog)) # These will not be the same
return new_dog
That print will print two sepeate addresses/IDs, indicating that they're distinct objects. The dog_id and dog_name objects will be the same, however.
It would return a new dog with those attributes assuming that Dog(id=id, name =dog_name) is your constructor. The program doesn't have a way to instead return existing dogs with the same attributes as you've written it. If you wanted to not create a new dog then you'd need to store the data of all the dogs and search for that specific data to ensure you return the same dog. This storage and search can be done through several ways like a dictionary, array/list, and so on (likely a dictionary is better for what you're trying to do).

How to avoid duplication of class instances in Python?

What is a good way to avoid duplication of a class instance when it is created using the __init__() function.
This question is a result of this issue.
Context (using employee class example):
Lets say I have an employee class: __init__(self,name,dept)
I also have a method, employee.info(self) that prints out name and dept of any employee.
However a user could just add an employee by calling a=employee(args..). They could do it multiple times using the same instance variable a, but different employee names.
This will cause issues if they try to print a.info(), as each time a different employee name will be printed.
Is there a better way to do this? I know it is possible to have the __init__() "pass" and define a new method to create an instance.
Expect results:
>>Adam=employee('marketing')
>>Adam.info()
>>Adam works in marketing.
OR
>>a=employee('Adam','marketing')
>>a=employee('Mary','marketing')
>>Error: employee instance with identifier "a" already exists.
>>Use employee.update() method to modify existing record.
Is there a cleaner way of doing it? (as you might guess, I am still learning python).
Or is it good practice to write an explicit function (instead of a class method) to add new employees?
what you try is impossible, because in
a=employee('Adam','marketing')
a is not an object but a variable that points to the object employee('Adam','marketing').
When you do
a=employee('Mary','marketing')
you say to python that now, a must now not point to the object employee('Adam','marketing') but to the object employee('Mary','marketing'). And then, if you have no more variable to reference the object employee('Adam','marketing'), the garbage collector will destroy it.
You must consider that in python all is object, but not the variables that are only references to manipulate objects.
I have been racking my brains over the same problem and have finally managed to figure out a workaround :
Create a dictionary that stores the employee name and the related object like this :
total_emp_dict = {}
Add this inside the def __init__ of the class employee : total_emp_dict[name] = self. This will ensure to add each employee name as key and the object associated will be added as value.
Now create a new function outside & before the employee class is defined, let's call it create_new_emp. It will go like this :
#function to check and avoid duplicate assignment of instances
def create_new_emp(name, dept):
if name in total_emp_dict:
return total_emp_dict[name]
else:
return employee(name, dept)
When creating a any new employee, use this new function : a = create_new_emp("Adam", HR) instead of a = employee("Adam", HR)
Explanation : This function will ensure that duplicate assignment is not done. If "a" is already assigned to "Adam", this function will return object of "Adam" to "a", when called again. But if nothing is assigned to "a", then this function will handover to the attributes (name, dept) to employee class and create a new instance. This instance will then be assigned to "a".
I don't know if this is the best solution for this problem, but honestly this is the only solution I have found so far and it works great for me without much fuss / extra code space. Hope it works for you too! :)

C# Inheritance access confusion

public class ABC
{
}
public class DEF : ABC
{
}
public class Class1
{
ABC abc = new DEF(); //No error
DEF def = new ABC(); //Compile time error
}
Can anyone explain to me this scenario.
and under what circumstances we might use it.
Its because as per the OOD rule you can assign child to parent but you cannot assign parent to child.
//this possible as you re assigning child to parent
ABC abc = new DEF(); //No error
//this is illegal as you are trying to assign child to parent directly
DEF def = new ABC(); //Compile time error
Reconsider your design again or if you want to convert parent object to child than you need method for that conversion directly its not possible to do it as per OOD rules.
Consider real time example relation of Customer and RetailCustomer or Corporatecustomer of bank. Where you can easily say RetailCustomer or CorporateCustomer is Customer, but you cannot say Customer is RetailCustomer or CorporateCustomer because customer can be of any type.
Same goes for relation between Parent Shape Class and Child Rectangle,Circle etc. class.
This is called as Ploymorphism .
As explained in MSDN
At run time, objects of a derived class may be treated as objects of a
base class in places such as method parameters and collections or
arrays. When this occurs, the object's declared type is no longer
identical to its run-time type.
Base classes may define and implement virtual methods, and derived
classes can override them, which means they provide their own
definition and implementation. At run-time, when client code calls the
method, the CLR looks up the run-time type of the object, and invokes
that override of the virtual method. Thus in your source code you can
call a method on a base class, and cause a derived class's version of
the method to be executed.
The answer of for this question is best explained here MSDN Polymorphism
Let's say ABC is Person, while DEF is Student (which is a subclass of Person). You can always treat a Student as a Person, so the assignment to abc (of type Person) of a Student is correct, but you cannot treat a generic Person as Student, so the assignment to def is wrong (for instance, you cannot get the student number of a person which is not a student)

Puppet: how can i pass value from inherited class to base class?

How can I pass value from inherited class to base class using puppet?
You can see below a simplified code for my trials.
class executor::app($base_dir = "/usr/local",
$run_command = undef,
$prefix_naming = undef) {
}
class app1(
$base_dir = ::app1::params::base_dir,
$prefix_naming = "reader",
$run_command = " ") inherits executor::app{
}
OK, for starters lets assume you have these classes in module format. If not, then that should be the first order of business.
Second, avoid inheritance. There is almost always a better way to do it. Especially don't inherit across modules. About the only time I can think it's useful is for defaulting class parameters.
The base_dir on class app1 will not get the default unless the class inherits cea::params::base_dir (leading :: not needed). Again, across modules shouldn't be done. app1::params much better -- or just put in a sane default and eliminate the need to inherit parameters all together.
For your actual question, if you want to get a variable in another class you can just reference it. Keep in mind that puppet doesn't guarantee compile order so you should tell it to evaluate the other class first:
class executor::app {
Class['app1'] -> Class['executor::app']
$other_app_var = $app1::base_dir
}
Or throw this data in hiera and look up the value.

Initialize class reference

I get null value of instrumentRented
when I run
public class RentalAgreement
{
private MusicalInstrument instrumentRented;
public RentalAgreement(Customer renter,
RentalDate dateRented,
MusicalInstrument instrumentRented){
customer = renter;
rentalDate = dateRented;
instrumentRented = instrumentRented;
How to initialize MusicalInstrument reference in RentalAgreement?
Use this.instrumentRented = instrumentRented;
Since the parameter has the same name as the field attribute, you need to prefix with an explicit this to specify the scope.
You must instantiate a class with the new operator.
So somehwere in your code must do
instrumentRented = new MusicalInstrument();
before you access it. After you have done this you can execute functions from that class.
instrumentRented.doSomething();
In the above code you seem to pass it in in the constructor, so this means the caller has to instantiate it.
However I would advise to adopt a naming convention where you can see if a variable is a class member or a local variable. In your above code the local variable has the same name as the parameter, so it will not be set as a member variable, instead you assign it to itself. You might get a warning about this, depending on the evironment (Not sure about this but Eclipse definitely warns somethign like this). This is called shadowing, so what you need to do is:
this.instrumentRented = instrumentRented;

Resources