What's the point of declaring variables outside of constructor? - python

Take the following example:
class User:
name = ""
def __init__(self, name):
self.name = name
What is the point of declaring name = "" if you have to specify name anyway when you construct it?

You'd have to ask the person that did it, since that is a very broad question. Maybe git blame will help.
In general there is no point. They're different things: class attribute and instance attribute. One would be data associated with the type of object, the other with individual instances of the object.

Related

How to get class instanced using variable inside of the class

I am trying to access a class instance. I can't assign the class to a variable when I load it and then use it because I need to access the class based on what the user enters.
i.e: user goes to link website.com/classes/y, I need to access the instance with the name y.
I already handle the link and can get "y" or whatever the user entered by itself.
I have the class code as follows:
class LoadModel:
existing_models = []
def __init__(self, model_path):
self.name = model_path.parent.name
self.__class__.existing_models.append(self.name)
For now, I can verify if the class exists using the existing_models list, but how will I be able to access it using the self.name?
I want to access it using LoadModel.name.
It sounds like you want to keep a dictionary of model names to instances. You could do that with something like:
class LoadModel:
modelsByName = {}
def __init__(self, model_path):
self.name = model_path.parent.name
self.modelsByName[self.name] = self
Furthermore if you wanted to access an instance named name as LoadModel.name you could could add
setattr(self.__class__, self.name, self)
to __init__. Or if you were looking up by string (which it sounds like you might be) then you would just do LoadModel.modelsbyName[name].
Note also that you don't need to use self.__class__ when accessing members of the class that you have not assigned within the instance, and since you're only accessing the dictionary object defined in the class, you can use the reference inherited by the instance (self.modelsByName) instead of accessing the class explicitly (self.__class__.modelsByName).

method to print name of an instance of a class

I am new to classes and writing one to perform a tracking and timing task. Have looked at this but still having trouble getting one aspect of the functionality to work.
Here's the part of what I've got to demonstrate the problem:
class seperate_trackers():
def __init__(self):
print ("class initiated")
def print_instance_name(self):
print (self.__class__.__name__)
Create an instance of it:
track_task1 = separate_trackers()
>> class initiated
Run the method in there:
track_task1.print_instance_name()
>> separate_trackers
That's not what I want!
How can that method be fixed so it returns track_task1 when it is run?
This is not a good idea. If you want your instance to have a name, that should be an attribute of the instance itself (the name of the variabe is just a pointer and it should not represent the object's state).
Try this instead:
# We don't usually use snake case for class names in python (and its 'separate')
class SeparateTrackers():
def __init__(self, name):
self.name = name
instance1 = SeparateTrackers("instance_name")
print(instance1.name) # instance_name
Objects don't know what variables refer to them. There can be any number of references to an object, and none of them is "the real one," they are all equally valid as names for the object. Furthermore, there may be no references that are simple names:
things = [1, "hello", separate_trackers(), 3.14]
There's no useful way to find out what variables refer to an object.
class SeparateTrackers:
def __init__(self, instance_name):
self.instance_name = instance_name
def __str__(self):
return self.instance_name
So you can use something like
a = SeparateTracker("first instance")
print(a) # print instance's name

Python, why do we have to inherit from 'list' class

I'm learning object oriented python and came across this issue where python is forcing me to inherit from built-in 'list' class to use append method.
class ContactSearch(list): #Why inherit from 'list'?
def search(self, name):
matching_contact = []
for contact in self:
if name in contact.name:
matching_contact.append(contact)
return matching_contact
Why can't I simply declare an empty list and append to it? For example it works find in the following code without inheriting from 'list class':
class Contact:
all_contacts = []
def __init__(self, name, email):
self.name = name
self.email = email
Contact.all_contacts.append(self)
In ContactSearch, matching_contact is temporary variable for result of searching. A instance of ContactSearch is list. So search method can use self in iterator. matching_contact is over when search method is done.
In Contact, all_contacts is class variable and all instance of Contact share this. Instance of Contact is NOT list. But you can access all contact using like Contact.all_contacts, and yes, it is list.
The difference is only where the data is stored. The one stores data in itself, and the another stores data in its variable.

use of self argument

I am a newcomer to Python. I don't understand how/why the self argument is used:
class Person:
def __init__(self, name):
self.name = name
def sayHi(self):
print 'Hello, my name is', self.name
p = Person('Swaroop')
p.sayHi()
This code is from a Byte of Python. This code could have just as easily been written as:
def sayHi(self, name):
print 'Hello, my name is', name
p = Person('Swaroop')
p.sayHi()
...right? What is the purpose of making name a field of self?
It seems you are oversimplifying a not so simple thing.
In object-oriented programming, a Class is a Declarative Construct which gives a blueprint as to what an object (a manifestation of this blueprint) would contain (properties) and how it would behave (members).
Every manifestation of such a Class is called an Object which has a defined and specific instance. From an object via any of this behavioral attributes called member functions/methods we need somehow to refer to that instance of the object and remember individual elements within it and make a clear distinction with the other non member entities.
Consider Your example
class Person:
def __init__(self, name):
self.name = name
def sayHi(self):
print 'Hello, my name is', self.name
Every Instance of this Person (Tom, Dick, Harry) is unique and within each instance, to refer back to itself we need some idiom like (self in Python, this ptr is C++ or this in Java).
So in the __init__ method when you need to demarcate between the name attribute of Person with the name parameter we can easily do so with self. Not only that, at any instance we can keep on referring back to this name via the self.
Making an instance of Person p=Person('Swaroop') and then invoking sayHi contrasting to calling just a function sayHi which is not a part of an object has two implications
The Function is transient, has no state, no instance and its like Saying this Guy "Hey Mr. who ever you are say 'Hello, my name is Swaroop'". It's like on every run you have to make an imbecile make aware of his name who will forget the next moment you will meet him. It's like this Guy is suffering from Anterograde_amnesia. Calling sayHi of the instance of Person named Swaroop on the other hand would mean something like a physically existing Swaroop greeting back his Name who has a persistent memory and would never forget unless he adopts a new name.
The Function never remembers but forgets every time the call ends. The Person object will remember the name until you explicitly or implicitly Kill That Person.
If you have a background of C++ and might be wondering why on earth do we need to add that extra parameter to the function call where as in C++ this pointer is never passed.
Well Candidly speaking it does. If you read the C++ calling convention, whether X86 or X64, the this pointer is passed through the register ecx to the method to give an handle to itself. This is more explicit here where we deliberately pass the handle to the current instance to the method.
Have a look at the new method sayHiTo:
class Person:
def __init__(self, name):
self.name = name
def sayHi(self):
print 'Hello, my name is', self.name
def sayHiTo(self, other):
print 'Hello', other.name, ' my name is', self.name
p1 = Person('Swaroop')
p2 = Person('codeninja')
p1.sayHiTo(p2)
p2.sayHiTo(p1)
Actually no. Your second example is not correct.
The 'self' keyword is a special reference that is passed to instance methods of a class. It represents the actual instance of the class at that scope. When you make a class it is just a general definition. Then you create instances of that class. Each instance is unique and thus the methods have to be able to work on that instance. You have no way of knowing them until they are made so 'self' passes them in for you.
For instance, if you created two instances of your person class:
p1 = Person("john")
p2 = Person("sam")
self.name value is different for each of those. And when you call sayHi() on each instance:
p1.sayHi()
> Hello, my name is john
p2. sayHi()
> Hello, my name is sam
You would not use the self keyword for unbound functions. That is, just general functions like what you have written as your second example. You would instead have to write it like this;
def sayHi(name):
print 'Hello, my name is', name
p = Person('Swaroop')
p.sayHi()
> sayHi("john")
But that would basically just pass a name string to a Person class and call its method. The idea here is that you create unique instances of Person with their own properties.
The purpose is to store the reference to the name so you can reference it in another method of the class e.g. def sayHi (self)
You can't compare a function in a class to just a function. Sure you can pass in name, but the idea of using a class is that you are encapsulating data. Having vars linked to self means you can pass around an object, and that object can always have access to its 'member variables'. Some other class can use an instance of Person and not need to know that persons name in order to say hi.

Addressing instance name string in __init__(self) in Python

I am doing something like this:
class Class(object):
def __init__(self):
self.var=#new instance name string#
How do I make the __ init __ method of my instance to use the instance name string for 'c'? Say in case:
c=Class()
I want c.var equal to 'c'.
Thanks for your replies, I am implementing persistence and Class is persistent object's class. I want __ init __ to add an entry to the database when:
c=Class()
Then, suppose:
del c
Later on:
c=Class()
sholuld create an instance using data from database if there already is an entry 'c', otherwise create new entry.
Thanks for your replies, I am implementing persistence and Class is persistent object's class. I want __ init __ to add an entry to the database when:
c=Class()
Then, suppose:
del c
Later on:
c=Class()
sholuld create an instance using data from database if there already is an entry 'c', otherwise create new entry.
Python doesn't have variables, it has objects and names. When you do
c = Class()
you're doing two things:
Creating a new object of type Class
Binding the object to the name c in the current scope.
The object you created doesn't have any concept of a "variable name" -- If later you do
a = c
then the same object is accessible in exactly the same way using the names a and c. You can delete the name a, and the object would still exist.
If the objects you create need to have a name, the best way is to pass it to them explicitly,
class Class(object):
def __init__(self, name):
self.name = name
var = Class('var')
You can't do this. The reason for this is that the object of the class is created first, and only afterwards is this object bound to the name of the instance.
You can't (short of incredible hacks like examining the stack frame and inspecting the bytecode). There may not even be a name, or there could be multiple such names. What should be given for the following code fragments for instance:
l = [Class(), Class()]
a=b=c=d=Class()
I don't think this would be possible because the assignment to the variable of your new instance occours after the object is fully constructed and initialized and so you don't know the variable name it will be assigned to within init method
To persist data objects you need to use the database record's unique ID.
pesudo code because I don't know what database module you're using
import db # assume this is your db module
class Class(object):
def __init__(self):
self.id = None
self.name = None
def get_by_id(self, id):
records = db.execute('select * from table where id=%s' % str(id))
if records:
self.id = records[0]['id']
self.name = records[0]['name']
def save(self):
db.execute('update table set name=%s where id=%s' % (self.name, str(self.id)))
Again, this is pseudo code, the string injection technique I'm using is NOT advised as its fairly insecure, its just there to illustrate how to persist using classes with a db.
I am unaware of a way to access a variable's name programmatically without using deep reflection and a debugger. I do not think the information is available at runtime.
If you want to give instances a (unique?) name, you should probably make the initializer accept an extra argument.
def __init__(self, name):
self.name = name
And the caller should pass in the appropriate name:
c = Class("c")
This is a scope issue, you can't do what you're asking. Because c would be declared outside your class' scope, your instance is unaware of what its been named in code.
Perhaps if you can provide a broader explanation of what you're trying to accomplish a better solution can be suggested.
That isn't possible. You seem to be confusing variables and objects.
In any case there may well not be a variable:
e.g.
foo(Class())
Class().arbitraryMethod()
Or multiple:
a = b = Class()
I have the same thought several years ago. This is somekind of neat feature, but the language creator doesn't provide it. And I thought they are all fool to not discover this great feature.
But then come to think about that. I think the logic is impossible. say:
class Class(object):
def __init__(self):
self.instance_name.move() # self.instance_name refer to var
def move(self):
print "move"
var = Class()
now if the var is an array is that possible too ?
var[0] = Class() # i think it will get confused a bit
that's what i think of, i don't think that assigning the instance into itself is possible. and in some language I just sent the instance string into the object then using eval to execute the function

Categories

Resources