return name of object from class - python

how to return the name of the object-
class sampleclass:
def __init__(self):
pass
def __str__(self):
return self
dogfood = sampleclass
print(dogfood)
outputs this :
class '__main__.sampleclass'
..Trying to output dogfood

Reading the variable name is not possible easily.
You could instead use some kind of key-value store (dictionary). Then you can read out the name of the key under that a value is stored.

Attributes are one way to store a custom name string inside an object that can be retrieved later:
class sampleclass:
def __init__(self, name):
self.name = name
def __str__(self):
return self
sample_object = sampleclass('dogfood')
print(sample_object.name)
# Output: 'dogfood'

Related

Can i use 'self' in classes on its own?

I have a list of objects of the Person class. This list includes myself, so I need to remove "myself" from the list.
It means I need to remove the object from the list that calls this method.
class Population:
def __init__(self):
self.people = list()
class Person:
def __init__(self):
self.friends_list = list()
def make_friends(self, population, n):
temp_list = population.copy()
temp_list.remove(self)
self.friends_list.extend(random.sample(temp_list,n))
my test:
per = Person()
per2 = Person()
per3 = Person()
per4 = Person()
per5 = Person()
pop = [per,per2,per3,per4,per5]
for per in pop:
per.make_friends(pop, 2)
print('ME: ',per)
print(per.friends_list)
My tests run well, but there are general tests that check the code and they generate an error on this line:
try:
stud_res = person.make_friends(population, count)
except Exception:
print("\tPerson.make_friends() generated error")
return
Can I use self in this way, and if not, how can I better remove "myself" from the list?
It is a perfectly fine use case. By the way, note that you're overriding the builtin list.
To use self, you have to share a list collection between instances of a Person-class. In that case this collection should be declared as a class attribute or global list variable (not an instance attribute).
These samples of code are working:
with global list variable:
class Person:
def __init__(self, name):
self.name = name
def make_friends(self, list):
list.remove(self)
def __repr__(self):
return self.name
p1 = Person("Joe")
p2 = Person("Barack")
the_list = []
the_list.append(p1)
the_list.append(p2)
p1.make_friends(the_list)
print(the_list)
With class attribute:
class Person2:
class_list = []
def __init__(self, name):
self.name = name
Person2.class_list.append(self)
def make_friends(self):
Person2.class_list.remove(self)
def __repr__(self):
return self.name
p1 = Person2("Joe")
p2 = Person2("Barack")
print(Person2.class_list)
p1.make_friends()
print(Person2.class_list)
EDIT:
Variable 3 when a list of people is inside another class.
For accessing a list inside another class you could use attribute name or public method to get it if implemented:
class ClassWithList:
def __init__(self):
self.list_collection = []
def get_list(self):
return self.list_collection
class_with_list = ClassWithList()
class Person:
def __init__(self, name):
self.name = name
def make_friends(self, list):
list.remove(self)
def __repr__(self):
return self.name
p1 = Person("Joe")
p2 = Person("Barack")
# using implemented get-method of instance list attribute
class_with_list.get_list().append(p1)
class_with_list.get_list().append(p2)
print(class_with_list.get_list())
p1.make_friends(class_with_list.get_list())
print(class_with_list.get_list())
# instance list attribute of class`ClassWithList
print(class_with_list.list_collection)
p2.make_friends(class_with_list.list_collection)
print(class_with_list.list_collection)

how can i reference to an object variable without passing it as parameter in python classes

I am try to reference an object variable inside the class without passing it in parameters but it is throwing error
class Sample:
def __init__(self):
v = []
v.append(name)
v.append(email)
s = Sample()
s.name = "xxxx"
s.email = "ss#ss.com"
print s.v
error:
NameError: global name 'name' is not defined
I am assigning the variable name in the object now how can i call it inside the class without adding parameters to function
if you absolutely must avoid attributes:
class Sample:
def __init__(self):
self.v = []
def addName(self, name):
self.v.append(name)
def addEmail(self, email):
self.v.append(email)
s = Sample()
s.addName("xxxx")
s.addEmail("abc#def.com")
print(s.v)
Yet another way to do this is to use decorators and #property:
class Sample(object):
def __init__(self):
self.v = [None, None]
#property
def name(self):
return self.v[0]
#property
def email(self):
return self.v[1]
#name.setter
def name(self, value):
self.v[0] = value
#email.setter
def email(self, value):
self.v[1] = value
s = Sample()
s.name = "xxxx"
s.email = "ss#ss.com"
print s.v
Notes:
Your class must be extending object explicitly in python 2 for this to work
#property decorated methods are working as "getters" and return a value
#<name>.setter is a setter method responsible for setting <name> member, so #email.setter sets the email and is being invoked when x.email = ... is called
The above may be a bit long-winded but allows for a clean API which hides the details from the user... Some people do prefer to add get/set_name methods to be more explicit but the above is more pythonic
If your requirements are dynamic, you can create attributes at run time like,
class Sample:
pass
s = Sample()
setattr(s,"name","chanda")
setattr(s,"email","xyz#gmail.com")
setattr(s,"v",[s.name,s.email])
print(s.name) #chanda
print(s.email) #xyz#gmail.com
print(s.v) #['chanda', 'xyz#gmail.com']
print(s.__dict__) #{'email': 'xyz#gmail.com', 'v': ['chanda', 'xyz#gmail.com'], 'name': 'chanda'}

How to convert all elements automatically in a list to a given object in Python

I want to create a list child class that can convert all elements automatically in it to an object no matter the element is create by init or append or extend. So by using both for loop or getitem. Here's a simple example code. What kind of magic method should I use?
class A():
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Object A with name {}'.format(self.name)
class CustomerList(list):
def __init__(self, *args):
super(CustomerList, self).__init__(*args)
c = CustomerList('a')
c.append('b')
c[0] # Object A with name a
c[1] # Object A with name b
for ele in c:
print(c)
# Object A with name a
# Object A with name b
are you asking how to override __append__?
class A():
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Object A with name {}'.format(self.name)
class CustomerList(list):
def __init__(self, *args):
super(CustomerList, self).__init__(*args)
def append(self,letter):
super(CustomerList, self).append(A(letter))
I guess???.. but as mentioned in the comments if you want
my_custom_list.extend(["A","B","V"])
my_custom_list[2] = "A"
to work you will need to override
def __setitem__(self,key,value): # cover a[2]='A'
super(CustomerList,self).__setitem__(key,A(value))
def extend(self,other):
super(CustomerList,self).extend([A(val) for val in other])
of coarse you probably then need to override both __add__,__iadd__ at a minimum as well
I think what you're trying to do is: When you append a new item into the list, it is an object of class A. What you can do is override list.append function:
class A():
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Object A with name {}'.format(self.name)
class CustomerList(list):
def __init__(self, *args):
super(CustomerList, self).__init__(*args)
def append(self, arg):
new_obj = A(arg)
self.insert(len(self), new_obj)

Python: how to print instance variable of type string

I am trying to print a string variable returned by name() function, which in this case should print "Jim, but Python is printing
`<bound method Human.name of <__main__.Human object at 0x7f9a18e2aed0>>`
Below is the code.
class Human:
def __init__(self):
name = None
def setName(self, _name):
name = _name
def name(self):
return self.name
jim = Human()
jim.setName("Jim")
print(jim.name())
UPDATE:
After reading the answers, i updated the code as shown below, but, now i am getting a new error TypeError: 'str' object is not callable
class Human:
def __init__(self):
self.name = None
def setName(self, _name):
self.name = _name
def name(self):
return self.name
jim = Human()
jim.setName("Jim")
print(jim.name())
self.name is the method itself. You have no attributes storing the name. Nowhere do you actually set the name as an attribute. The following works:
class Human:
def __init__(self):
self.name = None
def setName(self, _name):
self.name = _name
# NOTE: There is no more name method here!
Now you have an actual attribute, and you don't need to call the method here:
jim = Human()
jim.setName("Jim")
print(jim.name) # directly using the attribute
You could even just set the attribute directly:
jim = Human()
jim.name = "Jim"
print(jim.name)
Alternatively, use self._name to store the name on the instance:
class Human:
_name = None
def setName(self, _name):
self._name = _name
def name(self):
return self._name
Here we used a class attribute Human._name as a default, and only set self._name on the instance in the Human.setName() method.
The problem is that name is the name of the internal variable in your object and also the name of the method.
The namespace for variables and methods is the same. Change the name of your method to something other than name. This will fix your getter. On first glance I thought that that would be all you have to do, but the recommendation in Martijn's answer also applies -- you need to assign to self.name and not just name in order to get your setter to work as well.
As an aside, this getter/setter pattern is not usually appropriate for Python. You should ask yourself why you want to use a getter/setter pattern over simply accessing the object's variable directly. See the section on getters and setters in this article for more detail.
You can use setter and getter properties instead of your custom defined methods.
class Human():
def __init__(self):
self._name = None
#property
def name(self):
return self._name
#name.setter
def name(self, name):
self._name = name
And then, use them:
jim = Human()
jim.name = "Jim"
print(jim.name)

Creating objects from static properties in python

I have a Category class which has different names for each categories, the names of the categories can be unknown, good and bad, all categories share the same behavior so i don't want to create sub classes for each type of category, the problem comes when i am trying to
create the different categories in this way:
Category.GOOD
This statement should return a category object with his name setting to 'good' so i try
the following:
class Category(object):
def __init__(self, name):
self.name = name
#property
def GOOD(self):
category = Category(name='good')
return category
#property
def BAD(self):
category = Category(name='bad')
return category
Then i created and use the category with the following output:
c = Category.GOOD
c.name
AttributeError: 'property' object has no attribute 'name'
Realizing that this doesn't work i try a java like approach:
class Category(object):
GOOD = Category(name='good')
BAD = Category(name='bad')
def __init__(self, name):
self.name = name
What i get here is a undefined name "Category" error, so my question is if there is a pythonic way to create a category object like this.
You probably want to use classmethods:
class Category(object):
#classmethod
def GOOD(cls):
category = cls(name='GOOD')
return category
Now you can do c = Category.GOOD().
You cannot do this with a property; you either have to use a classmethod, or create your own descriptor for that:
class classproperty(property):
def __get__(self, inst, cls):
return self.fget(cls)
I'm abusing the property decorator here; it implements __set__ and __del__ as well, but we can just ignore those here for convenience sake.
Then use that instead of property:
class Category(object):
def __init__(self, name):
self.name = name
#classproperty
def GOOD(cls):
return cls(name='good')
#classproperty
def BAD(cls):
return cls(name='bad')
Now accessing Category.GOOD works:
>>> Category.GOOD
<__main__.Category object at 0x10f49df50>
>>> Category.GOOD.name
'good'
I'd use module variables for this. Consider you have the module category.py:
class Category(object):
# stuff...
now you put the two global objects in it:
GOOD = Category(name='good')
BAD = Category(name='bad')
You can use it like that:
from path.to.category import GOOD, BAD
I don't say that this is pythonic but I think this approach is elegant.
The main point that you could not use class definition inside that class definition itself. So the most straight way to achieve what you are want is to use class/static methods as shown below, or even package constants.
class Category(object):
def __init__(self, name):
self.name = name
#classmethod
def GOOD(cls):
return Category(name='good')
#classmethod
def BAD(cls):
return Category(name='bad')
print Category.GOOD().name
or
class Category(object):
def __init__(self, name):
self.name = name
#staticmethod
def GOOD():
return Category(name='good')
#staticmethod
def BAD():
return Category(name='bad')
print Category.GOOD().name

Categories