I'm creating a structure of classes for a wrapper of an API I'm currently writing.
I have multiple classes defined inside my models file. I want to assign the default value of some attributes of classes to other classes. When I do this, I get a NameError because sometimes I try to use classes that are defined below the current class, thus Python does not know these classes yet. I've tried multiple solutions but none of them seem to work. Does anybody know an alternative or has experience with this?
my classes I've defined:
class RateResponse(BaseModel):
def __init__(self,
provider=Provider()
):
self.provider = provider
class Provider(ObjectListModel):
def __init__(self):
super(Provider, self).__init__(list=[], listObject=ProviderItem)
#property
def providerItems(self):
return self.list
class ProviderItem(BaseModel):
def __init__(self,
code=None,
notification=Notification(),
service=Service()
):
self.code = code
self.notification = notification
self.service = service
As you can see above, I'm initialising the attribute 'provider' on the class RateResponse with the an empty object of the class Provider, which is defined below it. I'm getting a NameError on this line because it's defined below RateResponse.
provider=Provider()
NameError: name 'Provider' is not defined
The simple solution to above would be to shift the places of the classes. However, this is only a snippet of my file that is currently 400 lines long, all with these types of classes and initializations. It would be impossible to order them all correctly.
I've looked up some solutions where I thought I could return an empty object of a class by a string. I thought the function would only evaluate after all the classes were defined, but I was wrong. This is what I tried:
def getInstanceByString(classStr):
return globals()[classStr]()
class RateResponse(BaseModel):
def __init__(self,
provider=getInstanceByString('Provider')
):
self.provider = provider
But to no avail. Does anybody have experience with this? Is this even possible within Python? Is my structure just wrong? Any help is appreciated. Thanks.
This code might not mean what you want it to mean:
class RateResponse(BaseModel):
def __init__(self,
provider=Provider()
):
...
This code is saying that when this class is declared you want to make an instance of Provider which will be the default value for the provider parameter.
You may have meant that the default argument should be a new instance of Provider for each client that makes an instance of RateResponse.
You can use the Mutable Default Argument pattern to get the latter:
class RateResponse(BaseModel):
def __init__(self, provider=None):
if provider is None:
provider = Provider()
...
However, if you really do want a single instance when the client wants the default you could add a single instance below the Provider definition:
class Provider(ObjectListModel):
...
Singleton_Provider = Provider()
Then the RateResponse class could still use the current pattern, but instead perform this assignment inside the if:
if provider is None:
provider = Singleton_Provider
At the time that the assignment is performed, the Singleton_Provider will have been created.
I have 2 scripts, 1st is All_Methods, and another is All_Testcases, as I am using unittest framework, so here we go.
All_Methods is like:
class All_Services():
def abc(self):
x =1
def bca(self):
print "My Name is Taimoor"
self.abc()
def cba(self):
self.bca()
and on another script which is All_TestCases is like this:
from All_Methods import All_Services as service
class All_TestCases(unittest.TestCase):
def test_1_running_method(self)
service.cba(self)
Exception showing is:
AttributeError: 'All_TestCases' object has no attribute 'bca'
Kindly someone tell me, what I am missing here?
Thanks.
You are not using classes in the usual way when you pass in self to methods that you call on the class. Common is to call the methods on instances of the class and getting the self argument implicitly.
When you call Method.running_query_Athena(self) self is an instance of All_TestCases which does not have the method connecting_Athena.
Did you mean for All_TestCases to derive from All_Methods?
Why is All_Methods a class at all?
Use proper indentation since python is solely based on the basis of how the code is indented.
Please, Please use proper naming conventions; as advised under PEP 8.
You're trying to access an instance method without an instance.
Try the following:
class MyClass:
def my_instance_method(self):
return True
#classmethod
def my_class_method(cls):
return True
#staticmethod
def my_static_method():
return True
This won't work:
>> MyClass.my_instance_method()
TypeError: my_instance_method() missing 1 required positional argument: 'self'
but these will since they are not bound to a class instance being created.
MyClass.my_class_method()
MyClass.my_static_method()
An instance method requires that you instantiate the Class; meaning you use:
MyClass().my_instance_method()
Since you seem to want to set response_id on the class instance; using the self argument which denotes the class instance to get the response_id. - I suggest that you use an instance method and instantiate the class as shown above (note the () after the class name)
Kindly do fix your formatting in the question.
There are quite a few things wrong with the code in the example, but putting that aside.
The error is caused by passing an instance of class A as the self argument to a (non-static) method of class B.
Python will attempt to call this method on the instance of class A, resulting in the missing attribute error.
Here is a simplified example of the problem:
class A:
def is_ham(self):
# Python secretly does `self.is_ham()` here,
# because `self` is the current instance of Class A.
# Unless you explicitly pass `self` when calling the method.
return True
class B:
def is_it_ham(self):
# Note, `self` is an instance of class B here.
return A.is_ham(self)
spam = B()
spam.is_it_ham()
I come from a .NET and Javascript background and I'm working my way up to learn Python (for Raspberry Pi).
Right now I'm trying to figure out OOP in Python and the use of methods and classes. But having a little issue with #staticmethod
class Car(object):
"""description of class"""
def __init__(self, make, model):
self.make = make
self.model = model
#staticmethod
def makeFirstNoise():
print("Vrooooommm!")
def makeSecondNoise():
print("Mweeeeeeeeeh!")
This is how I implement my class and try to run both methods.
from Car import Car
mustang = Car('Ford', 'Mustang')
mustang.makeFirstNoise()
mustang.makeSecondNoise()
This is the output:
Vrooooommm!
Traceback (most recent call last):
File "D:\Dev\T\PythonHelloWorld\PythonHelloWorld\PythonHelloWorld.py", line 5, in <module>
mustang.makeSecondNoise()
TypeError: makeSecondNoise() takes 0 positional arguments but 1 was given
So question, why can't I execute the second method without my staticmethod attribute? This seems to work if I just return the text directly like this:
def makeSecondNoise():
return "Mweeeeeeeh!"
print(mustang.makeSecondNoise())
The reason makeSecondNoise is causing an error is because it is automatically passed one argument, self, because it's not declared as a staticmethod. self is the instance of the class that the function was called on. This is ultimately causing the error because makeSecondNoise isn't coded to accept any parameters; it'd be like doing this:
def something():
...
something("Foo")
Here's an example of how self works:
>>> class Car:
... def makenoise(self):
... print(self)
...
>>> mustang = Car()
>>> mustang.makenoise()
<__main__.Car object at 0x0000000005498B38> # We can see that "self" is a reference to "mustang"
Your problem isn't related to print (I couldn't get your example without print to work either) - it's related to the automatic passing of the self argument.
In Python all method calls (besides classmethods and staticmethods) explicitly passed object instance as first argument. Convention is to name this argument self. This explicit argument should be included in method signature:
class Car(object):
def makeSecondNoise(self): # note that method takes one argument
print("Mweeeeeeeeeh!")
After that you may call your method without any problems.
mustang = Car('Ford', 'Mustang')
mustang.makeSecondNoise()
In Java, this (which represents instance object) is passed implicitly to methods - this is a source of your confusion.
For different data types, like string, there are methods that you call by adding a dot after, such as:
"string {0}".format(stringy)
or
listx.remove(x)
How is the information being passed to the method? How can I write a function like that?
class YourObject(object):
def do_something(self):
print('doing something')
Then you can use your object:
your_object = YourObject()
your_object.do_something()
This shows how to create an object, and call a method on it (like theexamples you provided in your post).
There are way more in-depth tutorials/blogs about object creation and custom classes. A good place to start is always the standard documentation.
You can create a custom class and then include whatever methods you want. Below is an example:
>>> class MyClass(object): # Define class MyClass
... def __init__(self): # Define MyClass' constructor method
... self.name = "Me" # Make an attribute
... def getName(self): # Define method getName
... return self.name # Return MyClass' attribute name (self.name)
...
>>> test = MyClass() # Initialize (create an instance of) MyClass
>>> print test.getName() # Print the name attribute by calling the getName method
Me
>>>
Basically, you are working with OOP (Object-Oriented Programming). However, since this concept is so large, I can't demonstrate/explain everything you can do with it here (otherwise my post would be enormous). My advice is to research OOP and Python classes. There are many good tutorials you can find. I gave one above; here is another:
This article has a snippet showing usage of __bases__ to dynamically change the inheritance hierarchy of some Python code, by adding a class to an existing classes collection of classes from which it inherits. Ok, that's hard to read, code is probably clearer:
class Friendly:
def hello(self):
print 'Hello'
class Person: pass
p = Person()
Person.__bases__ = (Friendly,)
p.hello() # prints "Hello"
That is, Person doesn't inherit from Friendly at the source level, but rather this inheritance relation is added dynamically at runtime by modification of the __bases__attribute of the Person class. However, if you change Friendly and Person to be new style classes (by inheriting from object), you get the following error:
TypeError: __bases__ assignment: 'Friendly' deallocator differs from 'object'
A bit of Googling on this seems to indicate some incompatibilities between new-style and old style classes in regards to changing the inheritance hierarchy at runtime. Specifically: "New-style class objects don't support assignment to their bases attribute".
My question, is it possible to make the above Friendly/Person example work using new-style classes in Python 2.7+, possibly by use of the __mro__ attribute?
Disclaimer: I fully realise that this is obscure code. I fully realize that in real production code tricks like this tend to border on unreadable, this is purely a thought experiment, and for funzies to learn something about how Python deals with issues related to multiple inheritance.
Ok, again, this is not something you should normally do, this is for informational purposes only.
Where Python looks for a method on an instance object is determined by the __mro__ attribute of the class which defines that object (the M ethod R esolution O rder attribute). Thus, if we could modify the __mro__ of Person, we'd get the desired behaviour. Something like:
setattr(Person, '__mro__', (Person, Friendly, object))
The problem is that __mro__ is a readonly attribute, and thus setattr won't work. Maybe if you're a Python guru there's a way around that, but clearly I fall short of guru status as I cannot think of one.
A possible workaround is to simply redefine the class:
def modify_Person_to_be_friendly():
# so that we're modifying the global identifier 'Person'
global Person
# now just redefine the class using type(), specifying that the new
# class should inherit from Friendly and have all attributes from
# our old Person class
Person = type('Person', (Friendly,), dict(Person.__dict__))
def main():
modify_Person_to_be_friendly()
p = Person()
p.hello() # works!
What this doesn't do is modify any previously created Person instances to have the hello() method. For example (just modifying main()):
def main():
oldperson = Person()
ModifyPersonToBeFriendly()
p = Person()
p.hello()
# works! But:
oldperson.hello()
# does not
If the details of the type call aren't clear, then read e-satis' excellent answer on 'What is a metaclass in Python?'.
I've been struggling with this too, and was intrigued by your solution, but Python 3 takes it away from us:
AttributeError: attribute '__dict__' of 'type' objects is not writable
I actually have a legitimate need for a decorator that replaces the (single) superclass of the decorated class. It would require too lengthy a description to include here (I tried, but couldn't get it to a reasonably length and limited complexity -- it came up in the context of the use by many Python applications of an Python-based enterprise server where different applications needed slightly different variations of some of the code.)
The discussion on this page and others like it provided hints that the problem of assigning to __bases__ only occurs for classes with no superclass defined (i.e., whose only superclass is object). I was able to solve this problem (for both Python 2.7 and 3.2) by defining the classes whose superclass I needed to replace as being subclasses of a trivial class:
## T is used so that the other classes are not direct subclasses of object,
## since classes whose base is object don't allow assignment to their __bases__ attribute.
class T: pass
class A(T):
def __init__(self):
print('Creating instance of {}'.format(self.__class__.__name__))
## ordinary inheritance
class B(A): pass
## dynamically specified inheritance
class C(T): pass
A() # -> Creating instance of A
B() # -> Creating instance of B
C.__bases__ = (A,)
C() # -> Creating instance of C
## attempt at dynamically specified inheritance starting with a direct subclass
## of object doesn't work
class D: pass
D.__bases__ = (A,)
D()
## Result is:
## TypeError: __bases__ assignment: 'A' deallocator differs from 'object'
I can not vouch for the consequences, but that this code does what you want at py2.7.2.
class Friendly(object):
def hello(self):
print 'Hello'
class Person(object): pass
# we can't change the original classes, so we replace them
class newFriendly: pass
newFriendly.__dict__ = dict(Friendly.__dict__)
Friendly = newFriendly
class newPerson: pass
newPerson.__dict__ = dict(Person.__dict__)
Person = newPerson
p = Person()
Person.__bases__ = (Friendly,)
p.hello() # prints "Hello"
We know that this is possible. Cool. But we'll never use it!
Right of the bat, all the caveats of messing with class hierarchy dynamically are in effect.
But if it has to be done then, apparently, there is a hack that get's around the "deallocator differs from 'object" issue when modifying the __bases__ attribute for the new style classes.
You can define a class object
class Object(object): pass
Which derives a class from the built-in metaclass type.
That's it, now your new style classes can modify the __bases__ without any problem.
In my tests this actually worked very well as all existing (before changing the inheritance) instances of it and its derived classes felt the effect of the change including their mro getting updated.
I needed a solution for this which:
Works with both Python 2 (>= 2.7) and Python 3 (>= 3.2).
Lets the class bases be changed after dynamically importing a dependency.
Lets the class bases be changed from unit test code.
Works with types that have a custom metaclass.
Still allows unittest.mock.patch to function as expected.
Here's what I came up with:
def ensure_class_bases_begin_with(namespace, class_name, base_class):
""" Ensure the named class's bases start with the base class.
:param namespace: The namespace containing the class name.
:param class_name: The name of the class to alter.
:param base_class: The type to be the first base class for the
newly created type.
:return: ``None``.
Call this function after ensuring `base_class` is
available, before using the class named by `class_name`.
"""
existing_class = namespace[class_name]
assert isinstance(existing_class, type)
bases = list(existing_class.__bases__)
if base_class is bases[0]:
# Already bound to a type with the right bases.
return
bases.insert(0, base_class)
new_class_namespace = existing_class.__dict__.copy()
# Type creation will assign the correct ‘__dict__’ attribute.
del new_class_namespace['__dict__']
metaclass = existing_class.__metaclass__
new_class = metaclass(class_name, tuple(bases), new_class_namespace)
namespace[class_name] = new_class
Used like this within the application:
# foo.py
# Type `Bar` is not available at first, so can't inherit from it yet.
class Foo(object):
__metaclass__ = type
def __init__(self):
self.frob = "spam"
def __unicode__(self): return "Foo"
# … later …
import bar
ensure_class_bases_begin_with(
namespace=globals(),
class_name=str('Foo'), # `str` type differs on Python 2 vs. 3.
base_class=bar.Bar)
Use like this from within unit test code:
# test_foo.py
""" Unit test for `foo` module. """
import unittest
import mock
import foo
import bar
ensure_class_bases_begin_with(
namespace=foo.__dict__,
class_name=str('Foo'), # `str` type differs on Python 2 vs. 3.
base_class=bar.Bar)
class Foo_TestCase(unittest.TestCase):
""" Test cases for `Foo` class. """
def setUp(self):
patcher_unicode = mock.patch.object(
foo.Foo, '__unicode__')
patcher_unicode.start()
self.addCleanup(patcher_unicode.stop)
self.test_instance = foo.Foo()
patcher_frob = mock.patch.object(
self.test_instance, 'frob')
patcher_frob.start()
self.addCleanup(patcher_frob.stop)
def test_instantiate(self):
""" Should create an instance of `Foo`. """
instance = foo.Foo()
The above answers are good if you need to change an existing class at runtime. However, if you are just looking to create a new class that inherits by some other class, there is a much cleaner solution. I got this idea from https://stackoverflow.com/a/21060094/3533440, but I think the example below better illustrates a legitimate use case.
def make_default(Map, default_default=None):
"""Returns a class which behaves identically to the given
Map class, except it gives a default value for unknown keys."""
class DefaultMap(Map):
def __init__(self, default=default_default, **kwargs):
self._default = default
super().__init__(**kwargs)
def __missing__(self, key):
return self._default
return DefaultMap
DefaultDict = make_default(dict, default_default='wug')
d = DefaultDict(a=1, b=2)
assert d['a'] is 1
assert d['b'] is 2
assert d['c'] is 'wug'
Correct me if I'm wrong, but this strategy seems very readable to me, and I would use it in production code. This is very similar to functors in OCaml.
This method isn't technically inheriting during runtime, since __mro__ can't be changed. But what I'm doing here is using __getattr__ to be able to access any attributes or methods from a certain class. (Read comments in order of numbers placed before the comments, it makes more sense)
class Sub:
def __init__(self, f, cls):
self.f = f
self.cls = cls
# 6) this method will pass the self parameter
# (which is the original class object we passed)
# and then it will fill in the rest of the arguments
# using *args and **kwargs
def __call__(self, *args, **kwargs):
# 7) the multiple try / except statements
# are for making sure if an attribute was
# accessed instead of a function, the __call__
# method will just return the attribute
try:
return self.f(self.cls, *args, **kwargs)
except TypeError:
try:
return self.f(*args, **kwargs)
except TypeError:
return self.f
# 1) our base class
class S:
def __init__(self, func):
self.cls = func
def __getattr__(self, item):
# 5) we are wrapping the attribute we get in the Sub class
# so we can implement the __call__ method there
# to be able to pass the parameters in the correct order
return Sub(getattr(self.cls, item), self.cls)
# 2) class we want to inherit from
class L:
def run(self, s):
print("run" + s)
# 3) we create an instance of our base class
# and then pass an instance (or just the class object)
# as a parameter to this instance
s = S(L) # 4) in this case, I'm using the class object
s.run("1")
So this sort of substitution and redirection will simulate the inheritance of the class we wanted to inherit from. And it even works with attributes or methods that don't take any parameters.