I have number of subclasses all of which have number of methods whose names start with "on.."
eg.:
def on_index(self):
raise NotImplementedError()
def on_spiking_intent(self):
raise NotImplementedError()
def on_no_option(self):
raise NotImplementedError()
I would like to write a method in the superclass which prints a list of all the "on..." methods of its subclasses and specifies to which subclass the method belongs.
I guess this get_all_on_methods method need not be in the superclass, but it made sense to me to put it there as only the superclass unites the subclasses.
How should I go about this? I was thinking about somehow using decorators like putting
#onmethod
in front of every "on..." method or also somehow using an abstract class. But I actually don't know.
You can iterate over the subclasses of some class using the __subclasses__() method. You can check the namespace of the subclasses for attributes that start with "on_", so something to the effect of:
class Ur:
#classmethod
def get_all_on_methods(cls):
results = []
for klass in cls.__subclasses__():
for name, attribute in vars(klass).items():
if name.startswith("on_"):
results.append((attribute, klass))
return results
class Foo(Ur):
def on_index(self):
pass
def some_method(self):
pass
class Bar(Ur):
def on_spiking_intent(self):
pass
def another_method(self):
pass
This populates a list for illustration purposes, you could easily populate a dictionary or whatever you want instead.
Also, this gets any class attribute, so you might want to check if it is a method by using:
if callable(attribute) and name.startswith("on_"):
...
But that is up to you.
Here's the output you get in the above example:
In [2]: Ur.get_on_methods()
Out[2]:
[(<function __main__.Foo.on_index(self)>, __main__.Foo),
(<function __main__.Bar.on_spiking_intent(self)>, __main__.Bar)]
I have the next situation. The goal of the following method is to return the object created from the incoming string. So I have:
class Situation(Generator):
pass
And the method inside parent class:
class Generator(object):
def createsituation(self, stringsituation="situation"):
return "Instance of Situation"
The incoming string always equals to string "situation". Is it possible in python?
You can easily map strings to classes, yes. Classes are just more objects, you can store them in other Python objects.
You can manually build a dictionary mapping strings to classes:
classes = {'situation': Situation}
You can automate this a little by creating a class decorator, perhaps:
classes = {}
def register(cls):
classes[cls.__name__.lower()] = cls
return cls
#register
class Situation(Generator):
# ...
Each class you prefix with #register will be added to the dictionary, with the class name lowercased as the key.
or you can use the globals() function to get a dictionary of all globals in your module. The latter is a little... overkill and also a security hazard, you could end up giving end-users way more access than you bargained for, as that also gives them other classes and functions you didn't mean to expose.
Once you have a dictionary, just access the right class and call it:
class Generator(object):
def createsituation(self, stringsituation="situation"):
return classes[stringsituation]()
If I understood you correctly, you want to create the Situation object from Generator's createsituation method. So you need the appropriate constructor in Situation class with passed string as an argument. Little changes in your code will achieve this:
class Situation(object):
def __init__(self, string):
print string
class Generator(object):
def createsituation(self, stringsituation="situation"):
return Situation(stringsituation)
g = Generator()
sitObj = g.createsituation("new_situation") # prints "new_situation" from Situation constructor
I need to pass some 3rd party code a list of functions that accept a single parameter, e.g. list.
run_funcs([m1, m2])
My code (methods) are part of a class, therefore they take another self parameter.
class MyClass():
def m1(self, o):
return <something>
def m2(self, o):
return <something>
Can I somehow extract from an object instance a list of functions runnable by run_funcs?
I need to have the methods in the class because I need some initialization (build some lists) which the methods access.
I (think) I should be able to create a list of function from an instance (which will then have the self), but I am not sure how ...
If you have an instance of the class, you can access the methods on the instance:
mc = MyClass()
run_funcs([mc.m1, mc.m2])
If you want to inspect a class and print a name and
and function reference to each method which has an argspec
of two args see the code block below.
When inspecting the methods' argspec, if it has two args,
the first one in a class method is 'self', thus when calling,
it would only require one arg.
In the loop below: method[0] is the name and
method[1] is a method reference.
I haven't actually tried it but if you need to generate functions
from a class at runtime, I think this is down the correct path
to victory.
import inspect
class MyClass():
def m1(self, o):
return 'method1'
def m2(self, o):
return 'method2'
mc = MyClass()
for method in inspect.getmembers(mc):
if isinstance(method[1], type(mc.m1)):
if len(inspect.getfullargspec(method[1]).args) == 2:
print(f'mc.{method[0]}')
print(f' mc.{method[1]}')
>>> mc.m1
>>> mc.<bound method MyClass.m1 of <funcs_from_class.MyClass object at 0x11181e6d8>>
>>>mc.m2
>>> mc.<bound method MyClass.m2 of <funcs_from_class.MyClass object at 0x11181e6d8>>
I am generating objects using type for using some of the code that is previously written
# Assume that myAppObjDict is already initialized.
myAppObj=type("myAppClass", (object,),myAppObjDict)
Now I want to add a method say myValue()in it so that if I should be able to call
value=myAppObj.myValue()
What should be the approach?
You should add the methods to myAppObjDict before you create the class:
def myValue(self, whatever):
pass
myAppObjDict['myValue'] = myValue
# Assume that myAppObjDict is already initialized.
myAppObj=type("myAppClass", (object,),myAppObjDict)
Alternatively define a base class containing the methods and include it in your tuple of base classes.
class MyBase(object):
def myValue(self): return 42
# Assume that myAppObjDict is already initialized.
myAppObj=type("myAppClass", (MyBase,),myAppObjDict)
You should be able to assign any function to the class after creation:
def method(self):
print self.__class__.__name__
def my_class (object):
pass
my_class.method = method
o = my_class()
o.method()
You can do this assignment at any time, and all object will have the new method added, event those already created.
After all, Python is a dynamic language :)
For example—say I want to add a helloWorld() method to Python's dict type. Can I do this?
JavaScript has a prototype object that behaves this way. Maybe it's bad design and I should subclass the dict object, but then it only works on the subclasses and I want it to work on any and all future dictionaries.
Here's how it would go down in JavaScript:
String.prototype.hello = function() {
alert("Hello, " + this + "!");
}
"Jed".hello() //alerts "Hello, Jed!"
Here's a useful link with more examples— http://www.javascriptkit.com/javatutors/proto3.shtml
You can't directly add the method to the original type. However, you can subclass the type then substitute it in the built-in/global namespace, which achieves most of the effect desired. Unfortunately, objects created by literal syntax will continue to be of the vanilla type and won't have your new methods/attributes.
Here's what it looks like
# Built-in namespace
import __builtin__
# Extended subclass
class mystr(str):
def first_last(self):
if self:
return self[0] + self[-1]
else:
return ''
# Substitute the original str with the subclass on the built-in namespace
__builtin__.str = mystr
print str(1234).first_last()
print str(0).first_last()
print str('').first_last()
print '0'.first_last()
output = """
14
00
Traceback (most recent call last):
File "strp.py", line 16, in <module>
print '0'.first_last()
AttributeError: 'str' object has no attribute 'first_last'
"""
Just tried the forbbidenfruit!
here is the code, very simple!
from forbiddenfruit import curse
def list_size(self):
return len(self)
def string_hello(self):
print("Hello, {}".format(self))
if __name__ == "__main__":
curse(list, "size", list_size)
a = [1, 2, 3]
print(a.size())
curse(str, "hello", string_hello)
"Jesse".hello()
NOTE: this QA is marked as duplicate to this one, but IMO it asks for something different. I cannot answer there, so I am answering here.
Specifically, I wanted to inherit from str and add custom attributes. Existing answers (especially the ones saying you can't) didn't quite solve it, but this worked for me:
class TaggedString(str):
"""
A ``str`` with a ``.tags`` set and ``.kwtags`` dict of tags.
Usage example::
ts = TaggedString("hello world!", "greeting", "cliche",
what_am_i="h4cker")
(ts.upper(), ts.tags, ts.kwtags)
"""
def __new__(cls, *args, **kwargs):
return super().__new__(cls, args[0])
def __init__(self, s, *tags, **kwtags):
super().__init__()
self.tags = set(tags)
self.kwtags = kwtags
Hopefully this helps someone! Cheers,
Andres
Yes indeed, but you have to define a new class of the same type and it should inherit from that type.
For example:
class list(list):
def __init__(self, *args):
super().__init__(args)
def map(self, function):
return [function(i) for i in self]
a = list(1, 2, 3, 4, 5)
def double(i):
return i * 2
print(a.map(double))
Yes, by subclassing those types. See unifying types and classes in Python.
No, this doesn't mean that actual dicts will have this type, because that would be confusing. Subclassing a builtin type is the preferred way to add functionality.
class MyString:
def __init__(self, string):
self.string = string
def bigger_string(self):
print(' '.join(self.string))
mystring = MyString("this is the string")
mystring.bigger_string()
output
t h i s i s t h e s t r i n g
Dataclass in Python 3.7
from dataclasses import dataclass
#dataclass
class St:
text : str
def bigger(self) -> None:
self.text = list(self.text)
print(" ".join(self.text))
mys = St("Hello")
mys.bigger()
output
H e l l o
Yes, we can add custom methods and attributes to built-in python types. For example, let us say, you wanna define a new method inside the list class.
Let us think of defining a 'list' class and writing your own function like as follows :
class list:
def custom_method (self):
return("Hey, I'm a custom method of list class")
#lets create an object here
obj = list([1,2,3])
print(obj.custom_method())
#The above runs fine, but a list has append() method also right?? let's try it
print(obj.append(1))
"""Now you will get Attribute error : list object has no attribute append()"""
Because, when you define class having 'list' as class name, you will no longer be able to access the 'in-built list' class methods as 'list' is treated as a user-defined class rather than a inbuilt class.
So, in order to get rid of this error, you can inherit the properties/members of 'list' class and you can define own methods or attributes. So, in this way, you can call user-defined / in-built class methods using the same class name.
Here's how it looks :
#Extending in-built list class
class list(list):
def custom_method (self):
return("Hey, I'm a custom method of list class")
obj = list([1,2,3])
print(obj.custom_method())
obj.append(1)
print(obj)
It runs fine, and outputs modified list as [1,2,3,1].
NOTE : But when you do like this, it may create some ambiguity issues in long run like naming conflicts
For example, if you had a method having same signature that of an inbuilt function in user-defined class(say 'list' here), then it will be overridden without your knowledge or notice, thus you may not be able to use its original functionality in future. Considering the above code, if you ever define a method like append(self, value), the original functionality of append() will be lost.
So, it is better to use a different class name for your class name rather than same name as inbuilt class name
For example, you can declare a class like here as follows which does not raise any errors or you will not face any naming conflicts.
class custom_list(list):
def custom_method (self):
return("Hey, I'm a custom method of list class")
obj = custom_list([1,2,3])
print(obj.custom_method())
obj.append(1)
print(obj)
Subclassing is the way to go in Python. Polyglot programmers learn to use the right tool for the right situation - within reason. Something as artfully constructed as Rails (a DSL using Ruby) is painfully difficult to implement in a language with more rigid syntax like Python. People often compare the two saying how similar they are. The comparison is somewhat unfair. Python shines in its own ways. totochto.