List element Pointer in Python - python

My question comes from this page, while I would like to create a pointer(-like thing) for an list element. The element is a primitive value (string) so I have to create a FooWrapper class as that page says.
I know that by setting __repr__ one can directly access this value.
class FooWrapper(object):
def __init__(self, value):
self.value = value
def __repr__(self):
return repr(self.value)
>>> bar=FooWrapper('ABC')
>>> bar
'ABC'
>>> bar=FooWrapper(3)
>>> bar
3
Now I can use it as an reference of string:
>>> L=[3,5,6,9]
>>> L[1]=FooWrapper('ABC')
>>> L
[3,'ABC',6,9]
>>> this=L[1]
>>> this.value='BCD'
>>> print(L)
[3,'BCD',6,9]
So now I have a pointer-like this for the list element L[1].
However it is still inconvenient since I must use this.value='BCD' to change its value. While there exists a __repr__ method to make this directly return this.value, is there any similar method to make this='BCD' to do this.value='BCD' ? I know this changes the rule of binding.. but anyway, is it possible?
I would also appreciate if there is a better solution for a list element pointer.
Thank you in advance:)

I'm not sure exactly what you are trying to do, but you could do something like:
class FooWrapper(object):
def __init__(self, value):
self.value = value
def __repr__(self):
return 'FooWrapper(' + repr(self.value) + ')'
def __str__(self):
return str(self.value)
def __call__(self,value):
self.value = value
Here I got rid of your idea of using __repr__ to hide FooWrapper since I think it a bad idea to hide from the programmer what is happening at the REPL. Instead -- I used __str__ so that when you print the object you will print the wrapped value. The __call__ functions as a default method, which doesn't change the meaning of = but is sort of what you want:
>>> vals = [1,2,3]
>>> vals[1] = FooWrapper("Bob")
>>> vals
[1, FooWrapper('Bob'), 3]
>>> for x in vals: print(x)
1
Bob
3
>>> this = vals[1]
>>> this(10)
>>> vals
[1, FooWrapper(10), 3]
However, I think it misleading to refer to this as a pointer. It is just a wrapper object, and is almost certain to make dealing with the wrapped object inconvenient.
On Edit: The following is more of a pointer to a list. It allows you to create something like a pointer object with __call__ used to dereference the pointer (when no argument is passed to it) or to mutate the list (when a value is passed to __call__). It also implements a form of p++ called (pp) with wrap-around (though the wrap-around part could of course be dropped):
class ListPointer(object):
def __init__(self, myList,i=0):
self.myList = myList
self.i = i % len(self.myList)
def __repr__(self):
return 'ListPointer(' + repr(self.myList) + ',' + str(self.i) + ')'
def __str__(self):
return str(self.myList[self.i])
def __call__(self,*value):
if len(value) == 0:
return self.myList[self.i]
else:
self.myList[self.i] = value[0]
def pp(self):
self.i = (self.i + 1) % len(self.myList)
Used like this:
>>> vals = ['a','b','c']
>>> this = ListPointer(vals)
>>> this()
'a'
>>> this('d')
>>> vals
['d', 'b', 'c']
>>> this.pp()
>>> this()
'b'
>>> print(this)
b
I think that this is a more transparent way of getting something which acts like a list pointer. It doesn't require the thing pointed to to be wrapped in anything.

The __repr__ method can get a string however it wants to. Let's say it says return repr(self.value) + 'here'. If you say this = '4here', what should be affected? Should self.value be assigned to 4 or 4here? What if this had another attribute called key and __repr__ did return repr(self.key) + repr(self.value)? When you did this = '4here', would it assign self.key to the whole string, assign self.value to the whole string, or assign self.key to 4 and self.value to here? What if the string is completely made up by the method? If it says return 'here', what should this = '4here' do?
In short, you can't.

Self-Answer based on John Coleman's idea:
class ListPointer(object):
def __init__(self,list,index):
self.value=list[index]
list[index]=self
def __repr__(self):
return self.value
def __call__(self,value):
self.value=value
>>> foo=[2,3,4,5]
>>> this=ListPointer(foo,2)
>>> this
4
>>> foo
[2,3,4,5]
>>> this('ABC')
>>> foo
[2,3,'ABC',5]
>>> type(foo(2))
<class '__main__.ListPointer'>
ListPointer object accepts a list and an index, stores the list[index] in self.value and then substitutes the list element with self. Similarly a pp method can also be achieved, while the former element should be restored and the next element be substituted with self object. By directly referring foo[2] one also gets this object, which is what I want. (Perhaps this should be called as a reference rather than a pointer..)

Related

Extend str class in Python and modify its attribute value [duplicate]

Do you know of a Python library which provides mutable strings? Google returned surprisingly few results. The only usable library I found is http://code.google.com/p/gapbuffer/ which is in C but I would prefer it to be written in pure Python.
Edit: Thanks for the responses but I'm after an efficient library. That is, ''.join(list) might work but I was hoping for something more optimized. Also, it has to support the usual stuff regular strings do, like regex and unicode.
In Python mutable sequence type is bytearray see this link
This will allow you to efficiently change characters in a string. Although you can't change the string length.
>>> import ctypes
>>> a = 'abcdefghijklmn'
>>> mutable = ctypes.create_string_buffer(a)
>>> mutable[5:10] = ''.join( reversed(list(mutable[5:10].upper())) )
>>> a = mutable.value
>>> print `a, type(a)`
('abcdeJIHGFklmn', <type 'str'>)
class MutableString(object):
def __init__(self, data):
self.data = list(data)
def __repr__(self):
return "".join(self.data)
def __setitem__(self, index, value):
self.data[index] = value
def __getitem__(self, index):
if type(index) == slice:
return "".join(self.data[index])
return self.data[index]
def __delitem__(self, index):
del self.data[index]
def __add__(self, other):
self.data.extend(list(other))
def __len__(self):
return len(self.data)
...
and so on, and so forth.
You could also subclass StringIO, buffer, or bytearray.
How about simply sub-classing list (the prime example for mutability in Python)?
class CharList(list):
def __init__(self, s):
list.__init__(self, s)
#property
def list(self):
return list(self)
#property
def string(self):
return "".join(self)
def __setitem__(self, key, value):
if isinstance(key, int) and len(value) != 1:
cls = type(self).__name__
raise ValueError("attempt to assign sequence of size {} to {} item of size 1".format(len(value), cls))
super(CharList, self).__setitem__(key, value)
def __str__(self):
return self.string
def __repr__(self):
cls = type(self).__name__
return "{}(\'{}\')".format(cls, self.string)
This only joins the list back to a string if you want to print it or actively ask for the string representation.
Mutating and extending are trivial, and the user knows how to do it already since it's just a list.
Example usage:
s = "te_st"
c = CharList(s)
c[1:3] = "oa"
c += "er"
print c # prints "toaster"
print c.list # prints ['t', 'o', 'a', 's', 't', 'e', 'r']
The following is fixed, see update below.
There's one (solvable) caveat: There's no check (yet) that each element is indeed a character. It will at least fail printing for everything but strings. However, those can be joined and may cause weird situations like this: [see code example below]
With the custom __setitem__, assigning a string of length != 1 to a CharList item will raise a ValueError. Everything else can still be freely assigned but will raise a TypeError: sequence item n: expected string, X found when printing, due to the string.join() operation. If that's not good enough, further checks can be added easily (potentially also to __setslice__ or by switching the base class to collections.Sequence (performance might be different?!), cf. here)
s = "test"
c = CharList(s)
c[1] = "oa"
# with custom __setitem__ a ValueError is raised here!
# without custom __setitem__, we could go on:
c += "er"
print c # prints "toaster"
# this looks right until here, but:
print c.list # prints ['t', 'oa', 's', 't', 'e', 'r']
Efficient mutable strings in Python are arrays.
PY3 Example for unicode string using array.array from standard library:
>>> ua = array.array('u', 'teststring12')
>>> ua[-2:] = array.array('u', '345')
>>> ua
array('u', 'teststring345')
>>> re.search('string.*', ua.tounicode()).group()
'string345'
bytearray is predefined for bytes and is more automatic regarding conversion and compatibility.
You can also consider memoryview / buffer, numpy arrays, mmap and multiprocessing.shared_memory for certain cases.
The FIFOStr package in pypi supports pattern matching and mutable strings. This may or may not be exactly what is wanted but was created as part of a pattern parser for a serial port (the chars are added one char at a time from left or right - see docs). It is derived from deque.
from fifostr import FIFOStr
myString = FIFOStr("this is a test")
myString.head(4) == "this" #true
myString[2] = 'u'
myString.head(4) == "thus" #true
(full disclosure I'm the author of FIFOstr)
Just do this
string = "big"
string = list(string)
string[0] = string[0].upper()
string = "".join(string)
print(string)
'''OUTPUT'''
  > Big

Python equivalent of C++ member pointer

What would be the equivalent of a C++ member pointer in Python? Basically, I would like to be able to replicate similar behavior in Python:
// Pointer to a member of MyClass
int (MyClass::*ptMember)(int) = &MyClass::member;
// Call member on some instance, e.g. inside a function to
// which the member pointer was passed
instance.*ptMember(3)
Follow up question, what if the member is a property instead of a method? Is it possible to store/pass a "pointer" to a property without specifying the instance?
One way would obviously be to pass a string and use eval. But is there a cleaner way?
EDIT: There are now several really good answers, each having something useful to offer depending on the context. I ended up using what is described in my answer, but I think that other answers will be very helpful for whoever comes here based on the topic of the question. So, I am not accepting any single one for now.
Assuming a Python class:
class MyClass:
def __init__(self):
self.x = 42
def fn(self):
return self.x
The equivalent of a C++ pointer-to-memberfunction is then this:
fn = MyClass.fn
You can take a method from a class (MyClass.fn above) and it becomes a plain function! The only difference between function and method is that the first parameter is customarily called self! So you can call this using an instance like in C++:
o = MyClass()
print(fn(o)) # prints 42
However, an often more interesting thing is the fact that you can also take the "address" of a bound member function, which doesn't work in C++:
o = MyClass()
bfn = o.fn
print(bfn()) # prints 42, too
Concerning the follow-up with the properties, there are plenty answers here already that address this issue, provided it still is one.
The closest fit would probably be operator.attrgetter:
from operator import attrgetter
foo_member = attrgetter('foo')
bar_member = attrgetter('bar')
baz_member = attrgetter('baz')
class Example(object):
def __init__(self):
self.foo = 1
#property
def bar(self):
return 2
def baz(self):
return 3
example_object = Example()
print foo_member(example_object) # prints 1
print bar_member(example_object) # prints 2
print baz_member(example_object)() # prints 3
attrgetter goes through the exact same mechanism normal dotted access goes through, so it works for anything at all you'd access with a dot. Instance fields, methods, module members, dynamically computed attributes, whatever. It doesn't matter what the type of the object is, either; for example, attrgetter('count') can retrieve the count attribute of a list, tuple, string, or anything else with a count attribute.
For certain types of attribute, there may be more specific member-pointer-like things. For example, for instance methods, you can retrieve the unbound method:
unbound_baz_method = Example.baz
print unbound_baz_method(example_object) # prints 3
This is either the specific function that implements the method, or a very thin wrapper around the function, depending on your Python version. It's type-specific; list.count won't work for tuples, and tuple.count won't work for lists.
For properties, you can retrieve the property object's fget, fset, and fdel, which are the functions that implement getting, retrieving, and deleting the attribute the property manages:
example_bar_member = Example.bar.fget
print example_bar_member(example_object) # prints 2
We didn't implement a setter or deleter for this property, so the fset and fdel are None. These are also type-specific; for example, if example_bar_member handled lists correctly, example_bar_member([]) would raise an AttributeError rather than returning 2, since lists don't have a bar attribute.
I was not satisfied with the string approach and did some testing. This seems to work pretty well and avoids passing strings around:
import types
# Our test class
class Class:
def __init__(self, val):
self._val = val
def method(self):
return self._val
#property
def prop(self):
return self._val
# Get the member pointer equivalents
m = Class.method
p = Class.prop
# Create an instance
c1 = Class(1)
# Bind the method and property getter to the instance
m1 = types.MethodType(m, c1)
p1 = types.MethodType(p.fget, c1)
# Use
m1() # Returns 1
p1() # Returns 1
# Alternatively, the instance can be passed to the function as self
m(c1) # Returns 1
p.fget(c1) # Returns 1
I'm not a C++ programmer, so maybe I'm missing some detail of method pointers here, but it sounds like you just want a reference to a function that's defined inside a class. (These were of type instancemethod in Python 2, but are just type function in Python 3.)
The syntax will be slightly different --- instead of calling it like a method with object.reference(args), you'll call it like a function: reference(object, args). object will be the argument to the self parameter --- pretty much what the compiler would have done for you.
Despite the more C-like syntax, I think it still does what you wanted... at least when applied to a callable member like in your example. It won't help with a non-callable instance field, though: they don't exist until after __init__ runs.
Here's a demonstration:
#!/usr/bin/env python3
import math
class Vector(object):
def __init__(self, x, y):
self.x = x
self.y = y
return
def __str__(self):
return '(' + str(self.x) + ', ' + str(self.y) + ')'
def __repr__(self):
return self.__class__.__name__ + str(self)
def magnitude(self):
return math.sqrt(self.x ** 2 + self.y ** 2)
def print_dict_getter_demo():
print('Demo of member references on a Python dict:')
dict_getter = dict.get
d = {'a': 1, 'b': 2, 'c': 3, 'z': 26}
print('Dictionary d : ' + str(d))
print("d.get('a') : " + str(d.get('a')))
print("Ref to get 'a' : " + str(dict_getter(d, 'a')))
print("Ref to get 'BOGUS': " + str(dict_getter(d, 'BOGUS')))
print('Ref to get default: ' + str(dict_getter(d, 'BOGUS', 'not None')))
return
def print_vector_magnitude_demo():
print('Demo of member references on a user-defined Vector:')
vector_magnitude = Vector.magnitude
v = Vector(3, 4)
print('Vector v : ' + str(v))
print('v.magnitude() : ' + str(v.magnitude()))
print('Ref to magnitude: ' + str(vector_magnitude(v)))
return
def print_vector_sorting_demo():
print('Demo of sorting Vectors using a member reference:')
vector_magnitude = Vector.magnitude
v0 = Vector(0, 0)
v1 = Vector(1, 1)
v5 = Vector(-3, -4)
v20 = Vector(-12, 16)
vector_list = [v20, v0, v5, v1]
print('Unsorted: ' + str(vector_list))
sorted_vector_list = sorted(vector_list, key=vector_magnitude)
print('Sorted: ' + str(sorted_vector_list))
return
def main():
print_dict_getter_demo()
print()
print_vector_magnitude_demo()
print()
print_vector_sorting_demo()
return
if '__main__' == __name__:
main()
When run with Python 3, this produces:
Demo of member references on a Python dict:
Dictionary d : {'a': 1, 'c': 3, 'b': 2, 'z': 26}
d.get('a') : 1
Ref to get 'a' : 1
Ref to get 'BOGUS': None
Ref to get default: not None
Demo of member references on a user-defined Vector:
Vector v : (3, 4)
v.magnitude() : 5.0
Ref to magnitude: 5.0
Demo of sorting Vectors using a member reference:
Unsorted: [Vector(-12, 16), Vector(0, 0), Vector(-3, -4), Vector(1, 1)]
Sorted: [Vector(0, 0), Vector(1, 1), Vector(-3, -4), Vector(-12, 16)]
As you can see, it works with both builtins and user-defined classes.
Edit:
The huge demo above was based on an assumption: that you had a reference to the class, and that your goal was to "hold on to" to one of the class's methods for use on whatever instances of that class showed up sometime later.
If you already have a reference to the instance, it's much simpler:
d = {'a': 1, 'b': 2, 'c': 3, 'z': 26}
d_getter = d.get
d_getter('z') # returns 26
This is basically the same thing as above, only after the transformation from a function into a method has "locked in" the argument to self, so you don't need to supply it.
The way I would approach this in python is to use __getattribute__. If you have the name of an attribute, which would be the analog of the c++ pointer-to-member, you could call a.__getattribute__(x) to get the attribute whose name is stored in x. It's strings and dicts instead of offsets & pointers, but that's python.

How to check if a class member exists without getting exception

For primitive types I can use the if in : boolean check. But if I use the in syntax to check for the existence of a class member I get a NameError exception. Is there a way in Python to check without an exception? Or is the only way to surround in try except block?
Here is my sample code.
class myclass:
i = 0
def __init__(self, num):
self.i = num
mylist = [1,2,3]
if 7 in mylist:
print "found it"
else:
print "7 not present" #prints 7 not present
x = myclass(3)
print x.i #prints 3
#below line NameError: name 'counter' is not defined
if counter in x:
print "counter in x"
else:
print "No counter in x"
You can use hasattr
if hasattr(x, 'counter'):
# whatever
The error you get is because you are using counter (a name) and not 'counter' (the string). However, even if you were to use 'counter' it would not do what you expect, you will get TypeError: argument of type 'a' is not iterable - that is you cannot iterate over your custom object.
Instead, use hasattr (thanks to Jon for the suggestion).
>>> x = A(3)
>>> x.i
3
>>> hasattr(x, 'counter')
False
>>> hasattr(x, 'i')
True
You can make a __contains__ function in your class, which reports back what attributes are in the class using the in operator.
class myclass:
def __init__(self, num):
self.i = num
def __contains__(self, attribute_name):
return hasattr(self, attribute_name)
Then (almost) the same as your code would work well.
x = myclass(3)
print x.i #prints 3
# prints 'No counter in x'
if 'counter' in x:
print "counter in x"
else:
print "No counter in x"
Note that you need to pass the string of the attribute name, rather than the attribute itself.
The correct answer to your question depends a bit on what you mean by a member existing in an object. If you mean, does an instance variable exist on a given object, use hasattr as other answers have explained.
However, if you're creating your own collection type and want to check for a specific value in its contents, then you'll want to give your class a __contains__ method. That magic method is called to implement the in operator. Here's a trivial example, where I simply wrap up a list in my own object.
class MyListWrapper(object):
def __init__(self, iterable=[]):
self.list = list(iterable)
def __contains__(self, value):
return value in self.list
Test session:
>>> m = MyListWrapper(["foo", "bar"])
>>> "foo" in m
True

Python, lazy list

Is it possible to have a list be evaluated lazily in Python?
For example
a = 1
list = [a]
print list
#[1]
a = 2
print list
#[1]
If the list was set to evaluate lazily then the final line would be [2]
The concept of "lazy" evaluation normally comes with functional languages -- but in those you could not reassign two different values to the same identifier, so, not even there could your example be reproduced.
The point is not about laziness at all -- it is that using an identifier is guaranteed to be identical to getting a reference to the same value that identifier is referencing, and re-assigning an identifier, a bare name, to a different value, is guaranteed to make the identifier refer to a different value from them on. The reference to the first value (object) is not lost.
Consider a similar example where re-assignment to a bare name is not in play, but rather any other kind of mutation (for a mutable object, of course -- numbers and strings are immutable), including an assignment to something else than a bare name:
>>> a = [1]
>>> list = [a]
>>> print list
[[1]]
>>> a[:] = [2]
>>> print list
[[2]]
Since there is no a - ... that reassigns the bare name a, but rather an a[:] = ... that reassigns a's contents, it's trivially easy to make Python as "lazy" as you wish (and indeed it would take some effort to make it "eager"!-)... if laziness vs eagerness had anything to do with either of these cases (which it doesn't;-).
Just be aware of the perfectly simple semantics of "assigning to a bare name" (vs assigning to anything else, which can be variously tweaked and controlled by using your own types appropriately), and the optical illusion of "lazy vs eager" might hopefully vanish;-)
Came across this post when looking for a genuine lazy list implementation, but it sounded like a fun thing to try and work out.
The following implementation does basically what was originally asked for:
from collections import Sequence
class LazyClosureSequence(Sequence):
def __init__(self, get_items):
self._get_items = get_items
def __getitem__(self, i):
return self._get_items()[i]
def __len__(self):
return len(self._get_items())
def __repr__(self):
return repr(self._get_items())
You use it like this:
>>> a = 1
>>> l = LazyClosureSequence(lambda: [a])
>>> print l
[1]
>>> a = 2
>>> print l
[2]
This is obviously horrible.
Python is not really very lazy in general.
You can use generators to emulate lazy data structures (like infinite lists, et cetera), but as far as things like using normal list syntax, et cetera, you're not going to have laziness.
That is a read-only lazy list where it only needs a pre-defined length and a cache-update function:
import copy
import operations
from collections.abc import Sequence
from functools import partialmethod
from typing import Dict, Union
def _cmp_list(a: list, b: list, op, if_eq: bool, if_long_a: bool) -> bool:
"""utility to implement gt|ge|lt|le class operators"""
if a is b:
return if_eq
for ia, ib in zip(a, b):
if ia == ib:
continue
return op(ia, ib)
la, lb = len(a), len(b)
if la == lb:
return if_eq
if la > lb:
return if_long_a
return not if_long_a
class LazyListView(Sequence):
def __init__(self, length):
self._range = range(length)
self._cache: Dict[int, Value] = {}
def __len__(self) -> int:
return len(self._range)
def __getitem__(self, ix: Union[int, slice]) -> Value:
length = len(self)
if isinstance(ix, slice):
clone = copy.copy(self)
clone._range = self._range[slice(*ix.indices(length))] # slicing
return clone
else:
if ix < 0:
ix += len(self) # negative indices count from the end
if not (0 <= ix < length):
raise IndexError(f"list index {ix} out of range [0, {length})")
if ix not in self._cache:
... # update cache
return self._cache[ix]
def __iter__(self) -> dict:
for i, _row_ix in enumerate(self._range):
yield self[i]
__eq__ = _eq_list
__gt__ = partialmethod(_cmp_list, op=operator.gt, if_eq=False, if_long_a=True)
__ge__ = partialmethod(_cmp_list, op=operator.ge, if_eq=True, if_long_a=True)
__le__ = partialmethod(_cmp_list, op=operator.le, if_eq=True, if_long_a=False)
__lt__ = partialmethod(_cmp_list, op=operator.lt, if_eq=False, if_long_a=False)
def __add__(self, other):
"""BREAKS laziness and returns a plain-list"""
return list(self) + other
def __mul__(self, factor):
"""BREAKS laziness and returns a plain-list"""
return list(self) * factor
__radd__ = __add__
__rmul__ = __mul__
Note that this class is discussed also in this SO.

How do I get the string representation of a variable in python?

I have a variable x in python. How can i find the string 'x' from the variable. Here is my attempt:
def var(v,c):
for key in c.keys():
if c[key] == v:
return key
def f():
x = '321'
print 'Local var %s = %s'%(var(x,locals()),x)
x = '123'
print 'Global var %s = %s'%(var(x,locals()),x)
f()
The results are:
Global var x = 123
Local var x = 321
The above recipe seems a bit un-pythonesque. Is there a better/shorter way to achieve the same result?
Q: I have a variable x in python. How can i find the string 'x' from the variable.
A: If I am understanding your question properly, you want to go from the value of a variable to its name. This is not really possible in Python.
In Python, there really isn't any such thing as a "variable". What Python really has are "names" which can have objects bound to them. It makes no difference to the object what names, if any, it might be bound to. It might be bound to dozens of different names, or none.
Consider this example:
foo = 1
bar = foo
baz = foo
Now, suppose you have the integer object with value 1, and you want to work backwards and find its name. What would you print? Three different names have that object bound to them, and all are equally valid.
print(bar is foo) # prints True
print(baz is foo) # prints True
In Python, a name is a way to access an object, so there is no way to work with names directly. You might be able to search through locals() to find the value and recover a name, but that is at best a parlor trick. And in my above example, which of foo, bar, and baz is the "correct" answer? They all refer to exactly the same object.
P.S. The above is a somewhat edited version of an answer I wrote before. I think I did a better job of wording things this time.
I believe the general form of what you want is repr() or the __repr__() method of an object.
with regards to __repr__():
Called by the repr() built-in function
and by string conversions (reverse
quotes) to compute the “official”
string representation of an object.
See the docs here: object.repr(self)
stevenha has a great answer to this question. But, if you actually do want to poke around in the namespace dictionaries anyway, you can get all the names for a given value in a particular scope / namespace like this:
def foo1():
x = 5
y = 4
z = x
print names_of1(x, locals())
def names_of1(var, callers_namespace):
return [name for (name, value) in callers_namespace.iteritems() if var is value]
foo1() # prints ['x', 'z']
If you're working with a Python that has stack frame support (most do, CPython does), it isn't required that you pass the locals dict into the names_of function; the function can retrieve that dictionary from its caller's frame itself:
def foo2():
xx = object()
yy = object()
zz = xx
print names_of2(xx)
def names_of2(var):
import inspect
callers_namespace = inspect.currentframe().f_back.f_locals
return [name for (name, value) in callers_namespace.iteritems() if var is value]
foo2() # ['xx', 'zz']
If you're working with a value type that you can assign a name attribute to, you can give it a name, and then use that:
class SomeClass(object):
pass
obj = SomeClass()
obj.name = 'obj'
class NamedInt(int):
__slots__ = ['name']
x = NamedInt(321)
x.name = 'x'
Finally, if you're working with class attributes and you want them to know their names (descriptors are the obvious use case), you can do cool tricks with metaclass programming like they do in the Django ORM and SQLAlchemy declarative-style table definitions:
class AutonamingType(type):
def __init__(cls, name, bases, attrs):
for (attrname, attrvalue) in attrs.iteritems():
if getattr(attrvalue, '__autoname__', False):
attrvalue.name = attrname
super(AutonamingType,cls).__init__(name, bases, attrs)
class NamedDescriptor(object):
__autoname__ = True
name = None
def __get__(self, instance, instance_type):
return self.name
class Foo(object):
__metaclass__ = AutonamingType
bar = NamedDescriptor()
baaz = NamedDescriptor()
lilfoo = Foo()
print lilfoo.bar # prints 'bar'
print lilfoo.baaz # prints 'baaz'
There are three ways to get "the" string representation of an object in python:
1: str()
>>> foo={"a":"z","b":"y"}
>>> str(foo)
"{'a': 'z', 'b': 'y'}"
2: repr()
>>> foo={"a":"z","b":"y"}
>>> repr(foo)
"{'a': 'z', 'b': 'y'}"
3: string interpolation:
>>> foo={"a":"z","b":"y"}
>>> "%s" % (foo,)
"{'a': 'z', 'b': 'y'}"
In this case all three methods generated the same output, the difference is that str() calls dict.__str__(), while repr() calls dict.__repr__(). str() is used on string interpolation, while repr() is used by Python internally on each object in a list or dict when you print the list or dict.
As Tendayi Mawushe mentiones above, string produced by repr isn't necessarily human-readable.
Also, the default implementation of .__str__() is to call .__repr__(), so if the class does not have it's own overrides to .__str__(), the value returned from .__repr__() is used.

Categories

Resources