Classes Python and developing Stack - python

I have created my own LIFO container class Stack that supports the methods of push, len, pop, and a check on isEmpty. All methods appear to be working in my example calls, except for when I call a created instance of this class(in my example s) I receive a memory location for the created object when I want to see the actual contents of that object.
class Stack:
x = []
def __init__(self, x=None):
if x == None:
self.x = []
else:
self.x = x
def isEmpty(self):
return len(self.x) == 0
def push(self,p):
self.x.append(p)
def pop(self):
return self.x.pop()
def __len__(self):
return(len(self.x))
s = Stack()
s.push('plate 1')
s.push('plate 2')
s.push('plate 3')
print(s)
print(s.isEmpty())
print(len(s))
print(s.pop())
print(s.pop())
print(s.pop())
print(s.isEmpty())
I get the result of running this line print(s) to be <__main__.Stack object at 0x00000000032CD748>t when I would expect and am looking for ['plate 1','plate 2','plate3']

You need to also override __str__ or __repr__ if you want your class to have a different representation when printing. Something like:
def __str__(self):
return str(self.x)
should do the trick. __str__ is what is called by the str function (and implicitly called by print). The default __str__ simply returns the result of __repr__ which defaults to that funny string with the type and the memory address.

You need to override the default implementation of __repr__. Otherwise it will use the default implementation which returns an informal string representation of the class, in this case the type and memory address.
def __repr__(self):
return str(self.x)

Yes override __str__ and/or __repr__
Remember __repr__ can can evaled and return the same object if possible

Related

Automatic counter as a subclass of integer?

Is it possible to create a class of integer where an instance of a certain class (say AutomaticCounter) will increase itself by some number (say 1) each time it is called?
>>> n = AutomaticCounter(start=0)
>>> print(n)
1
>>> print(n)
2
This is what I have tried so far:
class AutomaticCounter(int):
def __init__(self):
self = 0
def __str__(self):
self = self + 1
return self
If you really, really, really need to mangle an immutable and built-in type, then you can create a kind-of "pointer" to it:
class AutomaticCounter(int):
def __new__(cls, *args, **kwargs):
# create a new instance of int()
self = super().__new__(cls, *args, **kwargs)
# create a member "ptr" and storing a ref to the instance
self.ptr = self
# return the normal instance
return self
def __str__(self):
# first, create a copy via int()
# which "decays" from your subclass to an ordinary int()
# then stringify it to obtain the normal __str__() value
value = str(int(self.ptr))
# afterwards, store a new instance of your subclass
# that is incremented by 1
self.ptr = AutomaticCounter(self.ptr + 1)
return value
n = AutomaticCounter(0)
print(n) # 0
print(n) # 1
print(n) # 2
# to increment first and print later, use this __str__() instead:
def __str__(self):
self.ptr = AutomaticCounter(self.ptr + 1)
return str(int(self.ptr))
This, however, doesn't make the type immutable per se. If you do print(f"{self=}") at the beginning of __str__() you'll see the instance is unchanged, so you effectively have a size of 2x int() (+ some trash) for your object and you access the real instance via self.ptr.
It wouldn't work with self alone as self is merely a read-only reference (created via __new__()) passed to instance's methods as the first argument, so something like this:
def func(instance, ...):
instance = <something else>
and you doing the assignment would, as mentioned by Daniel, simply assign a new value to the local variable named instance (self is just a quasi-standard name for the reference) which doesn't really change the instance. Therefore the next solution which looks similar would be a pointer and as you'd like to manipulate it the way you described, I "hid" it to a custom member called ptr.
As pointed out by user2357112, there is a desynchronization caused by the instance being immutable, therefore if you choose the self.ptr hack, you'll need to update the magic methods (__*__()), for example this is updating the __add__(). Notice the int() calls, it converts it to int() to prevent recursions.
class AutomaticCounter(int):
def __new__(cls, *args, **kwargs):
self = super().__new__(cls, *args, **kwargs)
self.ptr = self
return self
def __str__(self):
value = int(self.ptr)
self.ptr = AutomaticCounter(int(self.ptr) + 1)
return str(value)
def __add__(self, other):
value = other
if hasattr(other, "ptr"):
value = int(other.ptr)
self.ptr = AutomaticCounter(int(self.ptr) + value)
return int(self.ptr)
def __rmul__(self, other):
# [1, 2, 3] * your_object
return other * int(self.ptr)
n = AutomaticCounter(0)
print(n) # 0
print(n) # 1
print(n) # 2
print(n+n) # 6
However, anything that attempts to pull the raw value or tries to access it with C API will most likely fail, namely reverse operations e.g. with immutable built-ins should be the case as for those you can't edit the magic methods reliably so it's corrected in all modules and all scopes.
Example:
# will work fine because it's your class
a <operator> b -> a.__operator__(b)
vs
# will break everything because it's using the raw value, not self.ptr hack
b <operator> a -> b.__operator__(a)
with exception of list.__mul__() for some reason. When I find the code line in CPython, I'll add it here.
Or, a more sane solution would be to create a custom and mutable object, create a member in it and manipulate that. Then return it, stringified, in __str__:
class AutomaticCounter(int):
def __init__(self, start=0):
self.item = start
def __str__(self):
self.item += 1
return str(self.item)
There are two issues here. First, self isn't actually the object but rather a variable reference to the object. When you reassign self, you're not changing the object but merely causing the self variable, which only has local scope, to now reference some other object. The original object remains unchanged.
Second, unless you really know what you're doing (and I don't), it is, in my opinion, unadvisable to subclass immutable built-ins. What you can do is have the object have an integer attribute and then define the __getattr__ method to pass any attribute calls on to the integer.
class AutomaticCounter:
def __init__(self, start=0):
self.item = start
def __str__(self):
self.item += 1
return str(self.item)
def __getattr__(self, attr):
return getattr(self.item, attr)

Python Expert: how to inherit built-in class and override every member function w.r.t. the base-class member function?

It is known that in Python, due to optimization concerns, we cannot add/modify member functions of a built-in class, e.g., adding an sed function to the built-in str class to perform re.sub(). Thus, the only way to achieve so is to inherit the class (or subclassing). i.e.,
class String(str):
def __init__(self, value='', **kwargs):
super().__init__()
def sed(self, src, tgt):
return String(re.sub(src, tgt, self))
The problem with this is that after sub-classing, member functions return base-class instance instead of the inherited class instance. For example, I would like to chain String edits String(' A b C d E [!] ').sed(...).lower().sed(...).strip().sed('\[.*\]', '').split() and so on. However, functions such as .lower() and .strip() returns an str instead of String, so cannot perform .sed(...) afterwards. And I do not want to keep casting to String after every function call.
So I did a manual over-ride of every base-class methods as follows:
class String(str):
for func in dir(str):
if not func.startswith('_'):
exec(f'{func}=lambda *args, **kwargs: [(String(i) if type(i)==str else i) for i in [str.{func}(*args, **kwargs)]][0]')
def __init__(self, value='', **kwargs):
super().__init__()
def sed(self, src, tgt):
return String(re.sub(src, tgt, self))
However, not every member function returns a simple str object, e.g., for functions such as .split(), they return a list of str; other functions like .isalpha() or .find() return boolean or integer. In general, I want to add more string-morphing functions and do not want to manually over-ride member functions of each return type in order to return inherited-class objects rather than base-class objects. So is there a more elegant way of doing this? Thanks!
Python's built-in classes are not designed to support that style of inheritance
easily. Also, the whole idea seems flawed to my eye. Even if you do figure out
a way to solve the problem as you've framed it, what's the advantage over good
old functions?
# Special String objects with new methods.
s = String('foo bar')
result = s.sed('...', '...')
# Regular str instances passed to ordinary functions.
s = 'foo bar'
result = sed(s, '...', '...')
That said, here's one way to try. I have not tested it
extensively, it might have a flaw, and I would never use it in real code.
The basic idea is to capture objects returned during low-level
attribute access, and if the object is callable return
a wrapped version of it that will perform the needed
data conversions.
import re
from functools import wraps
class String(str):
def __getattribute__(self, attr):
obj = object.__getattribute__(self, attr)
return wrapped(obj) if callable(obj) else obj
def __init__(self, value='', **kwargs):
super().__init__()
def sed(self, src, tgt):
return re.sub(src, tgt, self)
def wrapped(func):
#wraps(func)
def wrapper(*xs, **kws):
obj = func(*xs, **kws)
return convert(obj)
return wrapper
def convert(obj):
if isinstance(obj, str):
return String(obj)
elif isinstance(obj, list):
return [convert(x) for x in obj]
elif isinstance(obj, tuple):
return tuple(convert(x) for x in obj)
else:
return obj
Demo:
s = String('foo bar')
got = s.sed('foo', 'bzz').upper().split()
print(got)
print(type(got))
print(type(got[0]))
Output:
['BZZ', 'BAR']
<class 'list'>
<class '__main__.String'>

python mutable string class not working correctly

I created a mutable String class in Python, based on the builtin str class.
I can change the first character, but when I call capitalize(), it uses the old value instead
class String(str):
def __init__(self, string):
self.string = list(string)
def __repr__(self):
return "".join(self.string)
def __str__(self):
return "".join(self.string)
def __setitem__(self, index, value):
self.string[index] = value
def __getitem__(self, index):
if type(index) == slice:
return "".join(self.string[index])
return self.string[index]
def __delitem__(self, index):
del self.string[index]
def __add__(self, other_string):
return String("".join(self.string) + other_string)
def __len__(self):
return len(self.string)
text = String("cello world")
text[0] = "h"
print(text)
print(text.capitalize())
Expected Output :
hello world
Hello world
Actual Output :
hello world
Cello world
Your implementation inherits from str, so it brings along all the methods that str implements. However, the implementation of the str.capitalize() method is not designed to take that into account. Methods like str.capitalize() return a new str object with the required change applied.
Moreover, the Python built-in types do not store their state in a __dict__ mapping of attributes, but use internal struct data structures) only accessible on the C level; your self.string attribute is not where the (C equivalent of) str.__new__() stores the string data. The str.capitalize() method bases its return value on the value stored in the internal data structure when the instance was created, which can't be altered from Python code.
You'll have to shadow all the str methods that return a new value, including str.capitalize() to behave differently. If you want those methods from returning a new instance to changing the value in-place, you have to do so yourself:
class String(str):
# ...
def capitalize(self):
"""Capitalize the string, in place"""
self.string[:] ''.join(self.string).capitalize()
return self # or return None, like other mutable types would do
That can be a lot of work, writing methods like these for every possible str method that returns an updated value. Instead, you could use a __getattribute__ hook to redirect methods:
_MUTATORS = {'capitalize', 'lower', 'upper', 'replace'} # add as needed
class String(str):
# ...
def __getattribute__(self, name):
if name in _MUTATORS:
def mutator(*args, **kwargs):
orig = getattr(''.join(self.string), name)
self.string[:] = orig(*args, **kwargs)
return self # or return None for Python type consistency
mutator.__name__ = name
return mutator
return super().__getattribute__(name)
Demo with the __getattribute__ method above added to your class:
>>> text = String("cello world")
>>> text[0] = "h"
>>> print(text)
hello world
>>> print(text.capitalize())
Hello world
>>> print(text)
Hello world
One side note: the __repr__ method should use repr() to return a proper representation, not just the value:
def __repr__(self):
return repr(''.join(self.string))
Also, take into account that most Python APIs that are coded in C and take a str value as input, are likely to use the C API for Unicode strings and so not only completely ignore your custom implementations but like the original str.capitalize() method will also ignore the self.string attribute. Instead, they too will interact with the internal str data.
This approach is inferior to the already suggested answers. There is more overhead because you don't get to just track things as a list, and isinstance(s, str) won't work, for example.
Another way to accomplish this is to subclass collections.UserString. It's a wrapper around the built-in string type that stores it as a member named data. So you could do something like
from collections import UserString
class String(UserString):
def __init__(self, string):
super().__init__(string)
def __setitem__(self, index, value):
data_list = list(self.data)
data_list[index] = value
self.data = "".join(data_list)
# etc.
And then you will get capitalize and the other string methods for free.
You inherited str's definition of capitalize, which ignores your class's behaviors and just uses the underlying data of the "real" str.
Inheriting from a built-in type like this effectively requires you to reimplement every method, or do some metaprogramming with __getattribute__; otherwise, the underlying type's behaviors will be inherited unmodified.

Python class object in array

I'm trying to make an array of class objects. When I create the object, it works great:
class Complex(object):
def __init__(self, realpart, imagpart):
#creates complex number
self.r = realpart
self.i = imagpart
def __str__(self):
'''Returns complex number as a string'''
return '(%s + %s j)' % (self.r, self.i)
a = Complex(1,0)
print a
(1 + 0 j)
But when I try to put a in an array, I get an error:
arr1 = [a]
[<__ main __.Complex object at 0x5afab0>]
Why could this be happening? Thanks in advance.
Because __repr__ was used instead of __str__. Override __repr__ as Ashwini Chaudhary commented.
>>> class Complex(object):
... def __init__(self, realpart, imagpart):
... self.r = realpart
... self.i = imagpart
... def __str__(self):
... '''Returns complex number as a string'''
... return '(%s + %s j)' % (self.r, self.i)
... __repr__ = __str__ # <-----
...
>>> a = Complex(1,0)
>>> [a]
[(1 + 0 j)]
As per the docs, print normally calls __str__, so when you printed the object, __str__ is invoked. But when you print the builtin collections, the __str__ method of them invoke __iter__ of the individual elements in it. So, your must implement __iter__ on your own, or let the default __repr__ as it is.
If you decide to implement __repr__ yourself, the docs say,
If at all possible, this should look like a valid Python expression
that could be used to recreate an object with the same value (given an
appropriate environment). If this is not possible, a string of the
form <...some useful description...> should be returned. The return
value must be a string object.
So, if you are implementing it yourself, give as much information as possible, so that the __repr__ output is unambiguous and useful for debugging.
def __str__(self):
'''Returns complex number as a string'''
return '< Complex({} + {}j) >'.format(self.r, self.i)
You can read more about this, in this answer.

How is lazy evaluation implemented (in ORMs for example)

Im curious to know how lazy evaluation is implemented at higher levels, ie in libraries, etc. For example, how does the Django ORM or ActiveRecord defer evaluation of query until it is actually used?
Let's have a look at some methods for django's django.db.models.query.QuerySet class:
class QuerySet(object):
"""
Represents a lazy database lookup for a set of objects.
"""
def __init__(self, model=None, query=None, using=None):
...
self._result_cache = None
...
def __len__(self):
if self._result_cache is None:
...
elif self._iter:
...
return len(self._result_cache)
def __iter__(self):
if self._result_cache is None:
...
if self._iter:
...
return iter(self._result_cache)
def __nonzero__(self):
if self._result_cache is not None:
...
def __contains__(self, val):
if self._result_cache is not None:
...
else:
...
...
def __getitem__(self, k):
...
if self._result_cache is not None:
...
...
The pattern that these methods follow is that no queries are executed until some method that really needs to return some result is called. At that point, the result is stored in self._result_cache and any subsequent call to the same method returns the cached value.
In Python, one object may "exist" - but its intrinsic value will only be known by the outer world at the moment it is used with one of the operators - since the operators are defined in the class by the magic names with double underscores, if a class writes the appropriate code to execute the deferred code when the operator is called, it is just fine.
That means, if the object's value is, for example, to be used like a string, any part of the program that will use the object will call, at some point, the "__str__" coercion method.
For example, let's create an object that behaves like a string, but tells the current time. Strings can be concatenated to other strings(__add__), can have their length requested (__len__), and so on. If we want it to fit perfectly in the place of a string, we'd have to override all methods. The idea is to retrieve the actual value just when one of the operators is called - otherwise, the actual object can freely be assigned to variables, and passed around. It will only be evaluated when its value is needed
Then, one can have some code like this:
class timestr(object):
def __init__(self):
self.value = None
def __str__(self):
self._getvalue()
return self.value
def __len__(self):
self._getvalue()
return len(self.value)
def __add__(self, other):
self._getvalue()
return self.value + other
def _getvalue(self):
timet = time.localtime()
self.value = " %s:%s:%s " % (timet.tm_hour, timet.tm_min, timet.tm_sec)
And using it on the console, you may have:
>>> a = timestr()
>>> b = timestr()
>>> print b
17:16:22
>>> print a
17:16:25
If the value for which you want a lazy evaluation is an attribute of your object (like Peson.name ) instead of what your object actually behaves like - it is even easier. Because Python allows all object attributes to be of a special type - called a descriptor -- which actually has a method called each time the attribute will be accessed. Therefore, one just has to create a class with a proper method named __get__ to fetch the actual value. This method will be called only when the attribute is needed.
Python even has an utility for easy descriptor creation - the "property" keyword, that makes this even easier - you pass a method that is the code to generate the attribute as the first parameter to property.
So, having an Event class with a lazy (and live) evaluated time, is just a matter of writting:
import time
class Event(object):
#property
def time(self):
timet = time.localtime()
return " %s:%s:%s " % (timet.tm_hour, timet.tm_min, timet.tm_sec)
And use it as in:
>>> e= Event()
>>> e.time
' 17:25:8 '
>>> e.time
' 17:25:10 '
The mechanism is quite simple:
class Lazy:
def __init__(self, evaluate):
self.evaluate = evaluate
self.computed = False
def getresult(self):
if not self.computed:
self.result = self.evaluate()
self.computed = True
return self.result
Then, this utility can be used as:
def some_computation(a, b):
return ...
# bind the computation to its operands, but don't evaluate it yet.
lazy = Lazy(lambda: some_computation(1, 2))
# "some_computation()" is evaluated now.
print lazy.getresult()
# use the cached result again without re-computing.
print lazy.getresult()
This implementation uses callables to represent the computation, but there are many variations on this theme (e.g. a base class that requires you to imlement an evaluate() method, etc.).
Not sure about the specifics about which library you talking about but, from an algorithm standpoint, I've always used/undertsood it as follows: (psuedo code from a python novice)
class Object:
#... Other stuff ...
_actual_property = None;
def interface():
if _actual_property is None:
# Execute query and load up _actual_property
return _actual_property
Essentially because the interface and implementation are separated, you can define behaviors to execute upon request.

Categories