If I have a class like that below (in reality, it has a lot more methods), and I want to load each method's results into a dictionary, is there a faster way to do features_to_dict, that's also modular if I add new methods?
from bs4 import BeautifulSoup
class CraigsPage():
def __init__(self, page_file):
self._page = open(page_file).read()
self.soup = BeautifulSoup(self._page)
self.title = self.soup.title.string
self.body = str(self.soup.find('section', id='postingbody'))
def get_title_char_count(self):
return len(list(self.title.replace(' ', '')))
def get_title_word_count(self):
return len(self.title.split())
def get_body_char_count(self):
return len(list(self.body.replace(' ', '')))
def features_to_dict(self):
feature_dict = {}
feature_dict['title_char_count'] = self.get_title_char_count()
feature_dict['title_word_count'] = self.get_title_word_count()
feature_dict['body_char_count'] = self.get_body_char_count()
return feature_dict
The inspect module is handy for this sort of stuff:
def features_to_dict(self):
members = inspect.getmembers(self, inspect.ismethod)
return {name: method() for name, method in members if name.startswith('get')}
Python classes have __dict__ attribute, that stores all attributes for the class as a dictionary. The following snippet iterates over __dict__ trying to find functions beginning with get, and automatically runs them, storing the results to a dict:
class A(object):
def get_a(self):
return 1
def get_b(self):
return 2
def features_to_dict(self):
self.d = {}
for f_name, f in A.__dict__.iteritems():
if 'get' in f_name:
self.d[f_name[4:]] = f(self)
a = A()
a.features_to_dict()
print a.d
This returns {'a': 1, 'b': 2}.
Use dir() method instead of dict attribute.
class A(object):
def method(self):
return 123
def call_all(self):
skip = dir(object) + ['call_all']
results = {}
for key in dir(self):
if key not in skip and callable(getattr(self, key)):
try:
results[key] = getattr(self, key)()
except Exception as e:
results[key] = e
return results
Kinda simple approach, to not use introspection at all and explicitly define which methods to call:
class A(object):
methods_to_call = [
"get_title_char_count",
"get_title_word_count",
"get_body_char_count",
]
...
def features_to_dict(self):
feature_dict = {}
for method in self.methods_to_call:
feature_dict[method[4:]] = getattr(self, method)()
return feature_dict
Related
working through "Learning Python: Powerful Object-Oriented Programming'
chapter 28 has you create a class that will list all instance attributes of an object.
then the book offers some ideas, such as listing all attributes up the inheritance tree. when doing so, i used the #classmethod decorator shown below - and was wondering if there's a way to filter those types of methods out of my listing:
"""Assorted class utilities and tools"""
class ShowAttrs(object):
"""
A class to show all available (including inherited, excluding special) attributes
"""
#classmethod
def getAttrs(cls, child_cls):
my_attrs = [_ for _ in child_cls.__dict__ if _.startswith('_') is False]
my_name = child_cls.__name__
listed_attrs = [my_name + ': ' + ', '.join(my_attrs)]
try:
bases = child_cls.__bases__
inherited_attrs = []
for base in bases[::-1]:
if base.__name__ != 'ShowAttrs' and base.__name__ != 'object':
inherited_lists = [ShowAttrs.getAttrs(base)]
for _ in inherited_lists:
inherited_attrs.extend(_)
except NameError:
return
inherited_attrs.extend(listed_attrs)
return inherited_attrs
def __repr__(self):
child_cls = self.__class__
all_attrs = ShowAttrs.getAttrs(child_cls)
len_attrs = reversed(list(range(len(all_attrs))))
all_attrs_unique = [ x for i,x in zip(len_attrs,all_attrs[::-1]) if i <= all_attrs.index(x) ]
return '\n'.join(reversed(all_attrs_unique))
if __name__ == '__main__':
class Parent(ShowAttrs):
var3 = 'Parent'
def parentMethod(self):
print('this is a Parent')
class Child(Parent):
var2 = 'Child'
def childMethod(self):
print('this is a Child')
class GrandChild(Child):
var1 = 'GrandChild'
#classmethod
def howCanIFilterThisOneOut(cls):
pass
def grandchildMethod(self):
print('this is a GrandChild')
def grandchildMethod2(self):
pass
def grandchildMethod3(self):
pass
class GrandChild2(Child):
var11 = 'GrandChild2'
class GreatGrandChild(GrandChild, GrandChild2):
var0 = 'GreatGrandChild'
x = GreatGrandChild()
print(x)
when i run this:
Python 3
x = GreatGrandChild()
print(x)
Console
Parent: var3, parentMethod
Child: var2, childMethod
GrandChild2: var11
GrandChild: var1,howCanIFilterThisOneOut, grandchildMethod, grandchildMethod2, grandchildMethod3
GreatGrandChild: var0
but howCanIFilterThisOneOut is a classmethod, not an instance method. so just wondering if it's possible to differentiate.
thanks
sandbox to try it:
https://edube.org/sandbox/af4390bc-77aa-11ec-ab3f-0242157e55ca
isinstance(x, classmethod) does the trick.
my_attrs = [
name for (name, value)
in child_cls.__dict__.items()
if not name.startswith('_') and not isinstance(value, classmethod)
]
As an aside, your code could simplify, with duplicate removal and all, into something like
import inspect
def get_fields(cls):
seen = set()
for cls in inspect.getmro(cls)[::-1]:
if cls is object:
continue
attr_names = {
name
for name in cls.__dict__
if name not in seen and not name.startswith("_")
}
seen.update(attr_names)
yield (cls.__name__, sorted(attr_names))
I created a child class that extends a single parameter from the Parent to *args and yields the outputs. However, it looks cleaner with a decorator instead of writing for arg in self.args: yield in multiple methods.
# Parent class
class _greet:
def _hello(self,name):
return "hello " + name
def _hey(self,name):
return "hey " + name
# Child class
class Greet(_greet):
def __init__(self,*names):
self.names = names
def hello(self):
for name in self.names:
yield super()._hello(name)
def hey(self):
for name in self.names:
yield super()._hey(name)
Although, all of my tries generated an error, because the decorator cannot "find" self.args.
Edit:
The idea behind this is to get something like:
class Greet(_greet):
def __init__(self,*names):
self.names = names
#args(names)
def hello(self, var=name):
super()._hello(var)
Firstly, It would be perfect if you could extend your parent-class with desired behaviour.
Secondly, you should think over the meaning of behaviour extending. Functions _hello and hello are fundamentally different. _hello takes one additional arg and returns created output. hello takes no additional args and creates generator. So may be you don't need to create child class? May be you need to create absolutely independent class (or new function)? Also all your functions in _greet doesn't use self arg - may be they should be static (via #staticmethod)?
Thirdly, are you sure that you need exactly decorators? There are something like 10 idioms I know to emulate same behaviour. Some of them have better productivity, some of them require a small amount of code. Some works with multiple inheritance - some do not. The realisation you have presented (if I understand it correctly) looks like adapter pattern (with mistakes).
Here it is adapter solution:
from itertools import repeat
class Greet(object):
age = 666
#staticmethod
def hello(name):
return f'hello {name}'
#staticmethod
def hey(name):
return f'hey {name}'
def say_age(self, name):
return f'{name} is {self.age} years old'
def multiple_greet_adapter(adapter):
return lambda self: map(adapter, repeat(self), self.names)
class MultipleGreet0(Greet):
def __init__(self, *names):
self.names = names
#multiple_greet_adapter
def hello_many(self, name):
return super().hello(name)
hey_many = multiple_greet_adapter(lambda self, name: super().hey(name))
say_age_many = multiple_greet_adapter(lambda self, name: super().say_age(name))
One of the disadvantages of such implementation is that you still have to write many similar code. Also this not as productive as we want.
Approach 1 - less code, but not productive as well:
from functools import partial
class MultipleGreet1(Greet):
def __init__(self, *names):
self.names = names
_corresponding_names = dict(
hello_many = 'hello',
hey_many = 'hey',
say_age_many = 'say_age',
)
def __getattr__(self, attr_name):
try:
single_greet_handler = getattr(super(), self._corresponding_names[attr_name])
except KeyError:
raise AttributeError()
else:
return partial(map, single_greet_handler, self.names)
Approach 2 - the same, but with descriptors:
class ManyGreets(object):
def __init__(self, attr_name):
self._attr_name = attr_name
def __get__(self, owner_inst, owner_cls):
if owner_inst is None:
return self
else:
return partial(map, getattr(super(owner_cls, owner_inst), self._attr_name), owner_inst.names)
class MultipleGreet2(Greet):
def __init__(self, *names):
self.names = names
hello_many = ManyGreets('hello')
hey_many = ManyGreets('hey')
say_age_many = ManyGreets('say_age')
Approach 3 - a good way you can do if MultipleGreet is independent class:
def _create_many_greets(single_greet_handler, method=True):
if method:
return lambda self: map(single_greet_handler, repeat(self), self.names)
else:
return lambda self: map(single_greet_handler, self.names)
class MultipleGreet3(object):
def __init__(self, *names):
self.names = names
age = 123
hello_many = _create_many_greets(Greet.hello, False)
hey_many = _create_many_greets(Greet.hey, False)
say_age_many = _create_many_greets(Greet.say_age)
Approach 4 - the way I recommend if MultipleGreet depends on Greet:
class ManyGreetsCreator(object):
def __init__(self, attr_name):
self._attr_name = attr_name
def __set_name__(self, owner_cls, set_name):
attr_name = self._attr_name
many_greets = lambda s: map(getattr(super(owner_cls, s), attr_name), s.names)
setattr(owner_cls, set_name, many_greets)
class MultipleGreet4(Greet):
def __init__(self, *names):
self.names = names
hello_many = ManyGreetsCreator('hello')
hey_many = ManyGreetsCreator('hey')
say_age_many = ManyGreetsCreator('say_age')
Tests:
>>> mg0 = MultipleGreet0('Nick', 'John')
>>> mg1 = MultipleGreet1('Nick', 'John')
>>> mg2 = MultipleGreet2('Nick', 'John')
>>> mg3 = MultipleGreet3('Nick', 'John')
>>> mg4 = MultipleGreet4('Nick', 'John')
>>> list(mg4.hello_many())
['hello Nick', 'hello John']
>>> list(mg0.hello_many()) == list(mg1.hello_many()) == list(mg2.hello_many()) ==\
list(mg3.hello_many()) == list(mg4.hello_many())
True
>>> list(mg0.say_age_many()) == list(mg1.say_age_many()) == list(mg2.say_age_many()) ==\
list(mg4.say_age_many())
True
>>> list(mg4.say_age_many())
['Nick is 666 years old', 'John is 666 years old']
>>> list(mg3.say_age_many())
['Nick is 123 years old', 'John is 123 years old']
You can read more about descriptors, about __getattr__, about super-class. There are also approaches based on __init_subclass__
I want to have simple representation of any class, like { property = value }, is there auto __repr__?
Simplest way:
def __repr__(self):
return str(self.__dict__)
Yes, you can make a class "AutoRepr" and let all other classes extend it:
>>> class AutoRepr(object):
... def __repr__(self):
... items = ("%s = %r" % (k, v) for k, v in self.__dict__.items())
... return "<%s: {%s}>" % (self.__class__.__name__, ', '.join(items))
...
>>> class AnyOtherClass(AutoRepr):
... def __init__(self):
... self.foo = 'foo'
... self.bar = 'bar'
...
>>> repr(AnyOtherClass())
"<AnyOtherClass: {foo = 'foo', bar = 'bar'}>"
Note that the above code will not act nicely on data structures that (either directly or indirectly) reference themselves. As an alternative, you can define a function that works on any type:
>>> def autoRepr(obj):
... try:
... items = ("%s = %r" % (k, v) for k, v in obj.__dict__.items())
... return "<%s: {%s}." % (obj.__class__.__name__, ', '.join(items))
... except AttributeError:
... return repr(obj)
...
>>> class AnyOtherClass(object):
... def __init__(self):
... self.foo = 'foo'
... self.bar = 'bar'
...
>>> autoRepr(AnyOtherClass())
"<AnyOtherClass: {foo = 'foo', bar = 'bar'}>"
>>> autoRepr(7)
'7'
>>> autoRepr(None)
'None'
Note that the above function is not defined recursively, on purpose, for the reason mentioned earlier.
Well, I played a little bit with other answers and got a very pretty solution:
class data:
#staticmethod
def repr(obj):
items = []
for prop, value in obj.__dict__.items():
try:
item = "%s = %r" % (prop, value)
assert len(item) < 20
except:
item = "%s: <%s>" % (prop, value.__class__.__name__)
items.append(item)
return "%s(%s)" % (obj.__class__.__name__, ', '.join(items))
def __init__(self, cls):
cls.__repr__ = data.repr
self.cls = cls
def __call__(self, *args, **kwargs):
return self.cls(*args, **kwargs)
You use it as a decorator:
#data
class PythonBean:
def __init__(self):
self.int = 1
self.list = [5, 6, 7]
self.str = "hello"
self.obj = SomeOtherClass()
and get a smart __repr__ out of the box:
PythonBean(int = 1, obj: <SomeOtherClass>, list = [5, 6, 7], str = 'hello')
This works with any recursive classes, including tree structures. If you try to put a self-reference in the class self.ref = self, the function will try (successfully) to work it out for about a second.
Of course, always mind your boss - mine would not like such a syntax sugar ))
Do you mean
__dict__
?
class MyClass:
def __init__(self, foo: str, bar: int):
self.foo = foo
self.bar = bar
self._baz: bool = True
def __repr__(self):
f"{self.__class__.__name__}({', '.join([f'{k}={v!r}' for k, v in self.__dict__.items() if not k.startswith('_')])})"
mc = MyClass('a', 99)
print(mc)
# MyClass(foo='a', bar=99)
# ^^^ Note that _baz=True was hidden here
I use this helper function to generate repr s for my classes. It is easy to run in a unittest function, ie.
def test_makeRepr(self):
makeRepr(Foo, Foo(), "anOptional space delimitedString ToProvideCustom Fields")
this should output a number of potential repr to the console, that you can then copy/paste into your class.
def makeRepr(classObj, instance = None, customFields = None):
"""Code writing helper function that will generate a __repr__ function that can be copy/pasted into a class definition.
Args:
classObj (class):
instance (class):
customFields (string):
Returns:
None:
Always call the __repr__ function afterwards to ensure expected output.
ie. print(foo)
def __repr__(self):
msg = "<Foo(var1 = {}, var2 = {})>"
attributes = [self.var1, self.var2]
return msg.format(*attributes)
"""
if isinstance(instance, classObj):
className = instance.__class__.__name__
else:
className=classObj.__name__
print('Generating a __repr__ function for: ', className,"\n")
print("\tClass Type: "+classObj.__name__, "has the following fields:")
print("\t"+" ".join(classObj.__dict__.keys()),"\n")
if instance:
print("\tInstance of: "+instance.__class__.__name__, "has the following fields:")
print("\t"+" ".join(instance.__dict__.keys()),"\n")
else:
print('\tInstance of: Instance not provided.\n')
if customFields:
print("\t"+"These fields were provided to makeRepr:")
print("\t"+customFields,"\n")
else:
print("\t"+"These fields were provided to makeRepr: None\n")
print("Edit the list of fields, and rerun makeRepr with the new list if necessary.\n\n")
print("repr with class type:\n")
classResult = buildRepr( classObj.__name__, " ".join(classObj.__dict__.keys()))
print(classResult,"\n\n")
if isinstance(instance, classObj):
instanceResult = buildRepr( instance.__class__.__name__, " ".join(instance.__dict__.keys()))
else:
instanceResult = "\t-----Instance not provided."
print("repr with instance of class:\n")
print(instanceResult,"\n\n")
if customFields:
customResult = buildRepr( classObj.__name__, customFields)
else:
customResult = '\t-----Custom fields not provided'
print("repr with custom fields and class name:\n")
print(customResult,"\n\n")
print('Current __repr__')
print("Class Object: ",classObj)
if instance:
print("Instance: ",instance.__repr__())
else:
print("Instance: ", "None")
def buildRepr(typeName,fields):
funcDefLine = "def __repr__(self):"
msgLineBase = ' msg = "<{typename}({attribute})>"'
attributeListLineBase = ' attributes = [{attributeList}]'
returnLine = ' return msg.format(*attributes)'
x = ['self.' + x for x in fields.split()]
xResult = ", ".join(x)
y = [x + ' = {}' for x in fields.split()]
yResult = ', '.join(y)
msgLine = msgLineBase.format(typename = typeName, attribute = yResult)
attributeListLine = attributeListLineBase.format(attributeList = xResult)
result = "{declaration}\n{message}\n{attributes}\n{returnLine}".format(declaration = funcDefLine,
message = msgLine,
attributes = attributeListLine,
returnLine =returnLine )
return result
To make #uzi's answer clearer, I have included more sample code. This is handy for a quick and dirty script:
class MyClass:
def __repr__(self):
return "MyClass:" + str(self.__dict__)
Is there any way to make a list of classes behave like a set in python?
Basically, I'm working on a piece of software that does some involved string comparison, and I have a custom class for handling the strings. Therefore, there is an instance of the class for each string.
As a result, I have a large list containing all these classes. I would like to be able to access them like list[key], where in this case, the key is a string the class is based off of (note: the string will never change once the class is instantiated, so it should be hashable).
It seems to me that I should be able to do this somewhat easily, by adding something like __cmp__ to the class, but either I'm being obtuse (likely), or I'm missing something in the docs.
Basically, I want to be able to do something like this (Python prompt example):
>>class a:
... def __init__(self, x):
... self.var = x
...
>>> from test import a
>>> cl = set([a("Hello"), a("World"), a("Pie")])
>>> print cl
set([<test.a instance at 0x00C866C0>, <test.a instance at 0x00C866E8>, <test.a instance at 0x00C86710>])
>>> cl["World"]
<test.a instance at 0x00C866E8>
Thanks!
Edit Some additional Tweaks:
class a:
... def __init__(self, x):
... self.var = x
... def __hash__(self):
... return hash(self.var)
...
>>> v = a("Hello")
>>> x = {}
>>> x[v]=v
>>> x["Hello"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'Hello'
>>> x["Hello"]
Just write a class that behaves a bit like a mapping:
class ClassDict(object):
def __init__(self):
self.classes = {}
def add(self, cls):
self.classes[cls.__name__] = cls
def remove(self, cls):
if self.classes[cls.__name__] == cls:
del self.classes[cls.__name__]
else:
raise KeyError('%r' % cls)
def __getitem__(self, key):
return self.classes[key]
def __repr__(self):
return 'ClassDict(%s)' % (', '.join(self.classes),)
class C(object):
pass
class D(object):
pass
cd = ClassDict()
cd.add(C)
cd.add(D)
print cd
print cd['C']
Why don't you just do:
>>> v = MyStr("Hello")
>>> x = {}
>>> x[v.val]=v
>>> x["Hello"]
MyStr("Hello")
Why go through all the trouble of trying to create a hand-rolled dict that uses different keys than the ones you pass in? (i.e. "Hello" instead of MyStr("Hello")).
ex.
class MyStr(object):
def __init__(self, val):
self.val = str(val)
def __hash__(self):
return hash(self.val)
def __str__(self):
return self.val
def __repr__(self):
return 'MyStr("%s")' % self.val
>>> v = MyStr("Hello")
>>> x = {}
>>> x[str(v)]=v
>>> x["Hello"]
MyStr("Hello")
Set and dict use the value returned by an object's __hash__ method to look up the object, so this will do what you want:
>>class a:
... def __init__(self, x):
... self.var = x
...
... def __hash__(self):
... return hash(self.var)
As I remember "set" and "dict" uses also __hash__
From Python 2.x doc:
A dictionary’s keys are almost arbitrary values. Values that are not hashable, that is, values containing lists, dictionaries or other mutable types (that are compared by value rather than by object identity) may not be used as keys.
Do you want something like this
class A(object):
ALL_INSTANCES = {}
def __init__(self, text):
self.text = text
self.ALL_INSTANCES[self.text] = self
a1 = A("hello")
a2 = A("world")
print A.ALL_INSTANCES["hello"]
output:
<__main__.A object at 0x00B7EA50>
I want to have simple representation of any class, like { property = value }, is there auto __repr__?
Simplest way:
def __repr__(self):
return str(self.__dict__)
Yes, you can make a class "AutoRepr" and let all other classes extend it:
>>> class AutoRepr(object):
... def __repr__(self):
... items = ("%s = %r" % (k, v) for k, v in self.__dict__.items())
... return "<%s: {%s}>" % (self.__class__.__name__, ', '.join(items))
...
>>> class AnyOtherClass(AutoRepr):
... def __init__(self):
... self.foo = 'foo'
... self.bar = 'bar'
...
>>> repr(AnyOtherClass())
"<AnyOtherClass: {foo = 'foo', bar = 'bar'}>"
Note that the above code will not act nicely on data structures that (either directly or indirectly) reference themselves. As an alternative, you can define a function that works on any type:
>>> def autoRepr(obj):
... try:
... items = ("%s = %r" % (k, v) for k, v in obj.__dict__.items())
... return "<%s: {%s}." % (obj.__class__.__name__, ', '.join(items))
... except AttributeError:
... return repr(obj)
...
>>> class AnyOtherClass(object):
... def __init__(self):
... self.foo = 'foo'
... self.bar = 'bar'
...
>>> autoRepr(AnyOtherClass())
"<AnyOtherClass: {foo = 'foo', bar = 'bar'}>"
>>> autoRepr(7)
'7'
>>> autoRepr(None)
'None'
Note that the above function is not defined recursively, on purpose, for the reason mentioned earlier.
Well, I played a little bit with other answers and got a very pretty solution:
class data:
#staticmethod
def repr(obj):
items = []
for prop, value in obj.__dict__.items():
try:
item = "%s = %r" % (prop, value)
assert len(item) < 20
except:
item = "%s: <%s>" % (prop, value.__class__.__name__)
items.append(item)
return "%s(%s)" % (obj.__class__.__name__, ', '.join(items))
def __init__(self, cls):
cls.__repr__ = data.repr
self.cls = cls
def __call__(self, *args, **kwargs):
return self.cls(*args, **kwargs)
You use it as a decorator:
#data
class PythonBean:
def __init__(self):
self.int = 1
self.list = [5, 6, 7]
self.str = "hello"
self.obj = SomeOtherClass()
and get a smart __repr__ out of the box:
PythonBean(int = 1, obj: <SomeOtherClass>, list = [5, 6, 7], str = 'hello')
This works with any recursive classes, including tree structures. If you try to put a self-reference in the class self.ref = self, the function will try (successfully) to work it out for about a second.
Of course, always mind your boss - mine would not like such a syntax sugar ))
Do you mean
__dict__
?
class MyClass:
def __init__(self, foo: str, bar: int):
self.foo = foo
self.bar = bar
self._baz: bool = True
def __repr__(self):
f"{self.__class__.__name__}({', '.join([f'{k}={v!r}' for k, v in self.__dict__.items() if not k.startswith('_')])})"
mc = MyClass('a', 99)
print(mc)
# MyClass(foo='a', bar=99)
# ^^^ Note that _baz=True was hidden here
I use this helper function to generate repr s for my classes. It is easy to run in a unittest function, ie.
def test_makeRepr(self):
makeRepr(Foo, Foo(), "anOptional space delimitedString ToProvideCustom Fields")
this should output a number of potential repr to the console, that you can then copy/paste into your class.
def makeRepr(classObj, instance = None, customFields = None):
"""Code writing helper function that will generate a __repr__ function that can be copy/pasted into a class definition.
Args:
classObj (class):
instance (class):
customFields (string):
Returns:
None:
Always call the __repr__ function afterwards to ensure expected output.
ie. print(foo)
def __repr__(self):
msg = "<Foo(var1 = {}, var2 = {})>"
attributes = [self.var1, self.var2]
return msg.format(*attributes)
"""
if isinstance(instance, classObj):
className = instance.__class__.__name__
else:
className=classObj.__name__
print('Generating a __repr__ function for: ', className,"\n")
print("\tClass Type: "+classObj.__name__, "has the following fields:")
print("\t"+" ".join(classObj.__dict__.keys()),"\n")
if instance:
print("\tInstance of: "+instance.__class__.__name__, "has the following fields:")
print("\t"+" ".join(instance.__dict__.keys()),"\n")
else:
print('\tInstance of: Instance not provided.\n')
if customFields:
print("\t"+"These fields were provided to makeRepr:")
print("\t"+customFields,"\n")
else:
print("\t"+"These fields were provided to makeRepr: None\n")
print("Edit the list of fields, and rerun makeRepr with the new list if necessary.\n\n")
print("repr with class type:\n")
classResult = buildRepr( classObj.__name__, " ".join(classObj.__dict__.keys()))
print(classResult,"\n\n")
if isinstance(instance, classObj):
instanceResult = buildRepr( instance.__class__.__name__, " ".join(instance.__dict__.keys()))
else:
instanceResult = "\t-----Instance not provided."
print("repr with instance of class:\n")
print(instanceResult,"\n\n")
if customFields:
customResult = buildRepr( classObj.__name__, customFields)
else:
customResult = '\t-----Custom fields not provided'
print("repr with custom fields and class name:\n")
print(customResult,"\n\n")
print('Current __repr__')
print("Class Object: ",classObj)
if instance:
print("Instance: ",instance.__repr__())
else:
print("Instance: ", "None")
def buildRepr(typeName,fields):
funcDefLine = "def __repr__(self):"
msgLineBase = ' msg = "<{typename}({attribute})>"'
attributeListLineBase = ' attributes = [{attributeList}]'
returnLine = ' return msg.format(*attributes)'
x = ['self.' + x for x in fields.split()]
xResult = ", ".join(x)
y = [x + ' = {}' for x in fields.split()]
yResult = ', '.join(y)
msgLine = msgLineBase.format(typename = typeName, attribute = yResult)
attributeListLine = attributeListLineBase.format(attributeList = xResult)
result = "{declaration}\n{message}\n{attributes}\n{returnLine}".format(declaration = funcDefLine,
message = msgLine,
attributes = attributeListLine,
returnLine =returnLine )
return result
To make #uzi's answer clearer, I have included more sample code. This is handy for a quick and dirty script:
class MyClass:
def __repr__(self):
return "MyClass:" + str(self.__dict__)