Making custom Attributes in Python - python

I'm new to python so I don't know much.
I was defining a function to work with lists and I want that function to be used like an attribute. For example to sort a list we use: list.sort()
Basically, instead of using the function like function(list) I want to use it like this: list.function()

You have to create a class
class MyClass():
def function(self, param):
print(param)
myClass = MYClass()
myClass.function()
You can see here or here for more details

You'll have to make a class that inherits the list class.
class MyList(list):
def __init__(self, *args):
super().__init__(*args)
def all_caps(self):
return [item.upper() if isinstance(item, str) else item for item in self]
mylist = MyList(['hi', 'hello', 1234])
mylist.all_caps()

You will have to create a custom class that inherit from original list and then using builtins module assign new extended class to previous list:
import builtins
class my_list(list):
def f(self):
return sum(self)
builtins.list = my_list
arr = list([1,2,3])
x = arr.f()
print(x)
Output:
6
Warning
Remember that you need to create every list using list() function to make sure your method will work.

Related

How to print out a list used as a class attribute or instance attribute

I've been playing with this for a little while now and can't see to figure it out. I have a simple class and want to use a list as either a shared class attribute or even just a instance attribute. Obviously, at some point it would be nice to see what is in this list, but all I can get to return is the object info (<__main__.Testclass instance at 0x7ff2a18c>). I know that I need to override the __repr__ or __str__ methods, but I'm definitely not doing it correctly.
class TestClass():
someList = []
def __init__(self):
self.someOtherList = []
def addToList(self, data):
self.someOtherList.append(data)
TestClass.someList.append(data)
def __repr__(self):
#maybe a loop here? I've tried returning list comprehensions and everything.
pass
test = TestClass()
test.addToList(1)
test.addToList(2)
test.addToList(3)
print(test.someList)
print(test.someOtherList)
I just want to see either [1,2,3] or 1 2 3 (hopefully choose either one).
With test.someList and test.someOtherList, you can already see what is inside those lists...
If you want to see those lists when printing the test object, you can either implement __str__ or __repr__ and delegate the representation of the instance to one of those. (either someList or someOtherList)
def __repr__(self):
return str(self.someOtherList)
Now whenever you print your test object, it shows the representation of self.someOtherList.
class TestClass:
someList = []
def __init__(self):
self.someOtherList = []
def addToList(self, data):
self.someOtherList.append(data)
TestClass.someList.append(data)
def __repr__(self):
return str(self.someOtherList)
test = TestClass()
test.addToList(1)
test.addToList(2)
test.addToList(3)
print(test)
output
[1, 2, 3]

How To Copy All Properties of Class Instance To New Instance

How would I copy all the properties of a class to a new instance of the class.
In the example below, with the way python works, when I use b=a, it assigns b and a to the same memory address. When i make a change to "b" the change is also made to "a."
Both elements of the list are stored at the same address
class test:
def __init__(self, name="Name",data=[]):
self.name=name
self.data=data
list=[]
a = test("First Name",["DATA1","DATA2","DATA3"])
b=a
list.append(a)
list.append(b)
I'm wanting to achieve something similar to how the list class allows you to do this to copy the list to a new memory address.
list1=[1,2,3]
list2=list(list1)
So in my case.
a = test("First Name",["DATA1","DATA2","DATA3"])
b=test(a)
without having to
b=test(a.name,a.data)
EDIT
Id like to achive the same effect as
b=copy.deepcopy(a)
but through this usage.
b=test(a)
Use copy:
import copy
b = copy.deepcopy(a)
You may want to write a copy constructor. For example...
import copy
class Foo:
def __init__(self, data):
self._data = data
#classmethod
def from_foo(cls, class_instance):
data = copy.deepcopy(class_instance._data)
return cls(data)
This achieved what I was wanting to do.
class Test:
def __init__(self, arg):
if isinstance(somearg, self.__class__):
self.__dict__ = somearg.__dict__.copy()
else:
self.var = arg
Usage:
a=Test(123)
b=Test(a)

Aliasing python variables without dict

I'm just implementing a class that requires an attribute to store a reference of another attribute as a cursor. See the following:
class foo:
def __init__(self):
self.egg=[4,3,2,1,[4,3,2,1]]
self.spam=#some reference or pointer analog represent self.egg[4][2], for example
def process(self):
# do something on self.egg[self.spam]
pass
I don't want a dict because self.spam should only represent one item, and using a dict I would have to consume indefinite unnecessary memory. Is there some pythonic way to implement self.spam above?
You could store the indices in self.spam, and use a property to access the value from self.egg given the current value of self.spam:
class Foo(object):
def __init__(self):
self.egg = [4,3,2,1,[4,3,2,1]]
self.spam = (4,2)
def process(self):
# do something on self.egg[self.spam]
print(self.eggspam)
pass
#property
def eggspam(self):
result = self.egg
for item in self.spam:
result = result[item]
return result
f = Foo()
f.process()
# 2
f.spam = (1,)
f.process()
# 3

How to make dictionary element an object in python?

How to make dictionary element an object in Python?
I made a class…
class Qs:
def __init__(self,list1,id,quest="",mark=1):
self.__list1=list1
self.__id=id
self.__quest=quest
self.__mark=mark
self.__list1.update({self.__id:{self.__quest:self.__mark}})
How can I store objects in a dictionary so I can call functions in this class like this?
dictionary[1].print()
what you probably want is another class that includes a dictionary in it:
class QuestionCollection:
def __init__(self):
self.listofquestions = dict()
def print(self,question_number):
print(dictionary[question_number])
Then you could do this:
classobject = MyClass()
classobject.listofquestions[1] = Qs(...)
classobject.print(1)
or,
classobject = MyClass()
print(classobject.dictionary[1])
Then, you could extend this class to include other functions that operate on your entire dictionary.

Can I iterate over a class in Python?

I have a class that keeps track of its instances in a class variable, something like this:
class Foo:
by_id = {}
def __init__(self, id):
self.id = id
self.by_id[id] = self
What I'd like to be able to do is iterate over the existing instances of the class. I can do this with:
for foo in Foo.by_id.values():
foo.do_something()
but it would look neater like this:
for foo in Foo:
foo.do_something()
is this possible? I tried defining a classmethod __iter__, but that didn't work.
If you want to iterate over the class, you have to define a metaclass which supports iteration.
x.py:
class it(type):
def __iter__(self):
# Wanna iterate over a class? Then ask that class for iterator.
return self.classiter()
class Foo:
__metaclass__ = it # We need that meta class...
by_id = {} # Store the stuff here...
def __init__(self, id): # new isntance of class
self.id = id # do we need that?
self.by_id[id] = self # register istance
#classmethod
def classiter(cls): # iterate over class by giving all instances which have been instantiated
return iter(cls.by_id.values())
if __name__ == '__main__':
a = Foo(123)
print list(Foo)
del a
print list(Foo)
As you can see in the end, deleting an instance will not have any effect on the object itself, because it stays in the by_id dict. You can cope with that using weakrefs when you
import weakref
and then do
by_id = weakref.WeakValueDictionary()
. This way the values will only kept as long as there is a "strong" reference keeping it, such as a in this case. After del a, there are only weak references pointing to the object, so they can be gc'ed.
Due to the warning concerning WeakValueDictionary()s, I suggest to use the following:
[...]
self.by_id[id] = weakref.ref(self)
[...]
#classmethod
def classiter(cls):
# return all class instances which are still alive according to their weakref pointing to them
return (i for i in (i() for i in cls.by_id.values()) if i is not None)
Looks a bit complicated, but makes sure that you get the objects and not a weakref object.
Magic methods are always looked up on the class, so adding __iter__ to the class won't make it iterable. However the class is an instance of its metaclass, so the metaclass is the correct place to define the __iter__ method.
class FooMeta(type):
def __iter__(self):
return self.by_id.iteritems()
class Foo:
__metaclass__ = FooMeta
...
Try this:
You can create a list with a global scope, define a list in the main module as follows:
fooList = []
Then add:
class Foo:
def __init__(self):
fooList.append(self)
to the init of the foo class
Then everytime you create an instance of the Foo class it will be added to the fooList list.
Now all you have to do is iterate through the array of objects like this
for f in fooList:
f.doSomething()
You can create a comprehension list and then call member methods as follows:
class PeopleManager:
def __init__(self):
self.People = []
def Add(self, person):
self.People.append(person)
class Person:
def __init__(self,name,age):
self.Name = name
self.Age = age
m = PeopleManager()
[[t.Name,t.Age] for t in m.People]
call to fill the object list:
m = PeopleManager()
m.Add( Person("Andy",38))
m.Add( Person("Brian",76))
You can create a class list and then call append in the init method as follows:
class Planet:
planets_list = []
def __init__(self, name):
self.name = name
self.planets_list.append(self)
Usage:
p1 = Planet("earth")
p2 = Planet("uranus")
for i in Planet.planets_list:
print(i.name)

Categories

Resources