I am new to programming so when I wanted a command to turn a hard-coded function's name into a string, I looked it up and started using the built-in __name__ function. The problem is that I don't think I understand how __name__ retrieves the wanted name. I know it has something to do with what is currently visible with local() or dir() but that's about it... (my own research on this topic has been kinda of hard to understand for me) As a result, I stumbled across an error that I don't know how to solve.
Here is some code that recreates my error:
class Abc:
#staticmethod
def my_static_func():
return
def my_method(self):
return
class_list = [my_static_func]
method_list = [my_method]
#These calls work
Abc.my_static_func.__name__
Abc.my_method.__name__
Abc.method_list[0].__name__
#But This call raises an AttributeError
Abc.class_list[0].__name__
I get this error message:
AttributeError: 'staticmethod' object has no attribute '__name__'
So why is that when I put my static method into a list and then try to get the function's name from the list it doesn't work? Please forgive me if this question is dumb. As you can clearly see, I don't understand the underlying principle of how __name__ works (and other stuff that I just don't know about to even give these topics names!). An answer would be nice but a reference to some docs would be also welcome.
With this code
#staticmethod
def my_static_method(...):
....
The function my_static_method is wrapped in a staticmethod. When you access a staticmethod from a class some magic happens to the staticmethod and you actually get a proper function back. Thats why you can access its __name__
Putting the staticmethod in a list and accessing it from that list prevents the magic from happening and you get the staticmethod object back.
Abc.my_static_func # this is a function
Abc.class_list[0] # this is a staticmethod object
As a staticmethod does not have a __name__ you get an AttibuteError when accessing its __name__.
To solve your problem you could get the underlying function from the staticmethod
Abc.class_list[0].__func__ # the function
Abc.class_list[0].__func__.__name__ # its name
To find out more about the "magic" that happens when you access attributes/methods from a class/object look up descriptors
Related
I am assuming this question has been asked a million times already but I can't seem to make sense of a few things so please bear with me here. I am trying to make do generic inheritance in Python. This is what I want to accomplish: I have a method that takes in a generic type and it returns a class that has been inherited from that parent class
this is what the code looks like
def make_foo(parent):
class Relationship(parent):
# def __init__(self):
#staticmethod
def should_see_this_method(self):
print("Hello here")
return True
return Relationship
Now this is the piece of code I am have
NewType = make_relationship(str)
another_test: NewType = "Hello"
another_test.should_see_this_method()
another_test.capitalize()
Now I am getting AttributeError: 'str' object has no attribute 'should_see_this_method'
I am not sure if this is anti pattern or not but I am just curios to know how I can do this.
thanks
This line:
another_test: NewType = "Hello"
doesn't do what you think it does.
This is a type hint. Hints are used by static type checkers, linters, and the like to check if your code has obvious bugs or is being used incorrectly. It helps you at "compile time" to catch things that are possible sources of errors, but it has no impact on the runtime behavior of the code.
Importantly, it does not construct an object of type NewType. It constructs a str. You can see this easily by calling type(another_test), which indicates this is a str. (It's also in the message of the AttributeError in your question.)
To actually construct that object, you have to do the usual thing:
>>> another_test = NewType("Hello")
>>> isinstance(another_test, NewType)
True
An unrelated problem in your code: staticmethods should not take self as the first argument. They are not bound to any instance. You'll see an error once you actually get to the line which calls the method.
While trying to set up a new slot and signal between a worker network QRunnable and code submitting it with callbacks (to handle network responses), I've got the following line of code:
exception_callback = QtCore.pyqtSlot('PyQt_PyObject', str)(exception_callback)
where exception_callback is a bound member function of some class instance. However, the aforementioned line fails with the following error:
AttributeError: 'instancemethod' object has no attribute '__pyqtSignature__'
What am I missing?
Edit:
A simple reproduction:
class A(QtCore.QObject):
def a(self):
print("Called")
a=A()
QtCore.pyqtSlot()(a.a)
Will raise the following exception:
AttributeError: 'instancemethod' object has no attribute '__pyqtSignature__'
A workaround I found is that wrapping the member function and using a closure around the member function, like so, will work:
QtCore.pyqtSlot()(lambda : a.a())
However this is a little messy and I rather not use the workaround without understanding it's necessity.
leaving this here in case someone else makes the same stupid mistake and fails spotting the error, like myself
In my reproduction example the error is quite clear and was relatively easy to spot. On line QtCore.pyqtSlot()(a.a) I'm mistakenly wrapping a bound instance method, where pyqt only allows using pyqtSlot at method/function definition time.
Simply using QtCore.pyqtSlot() as a decorator when defining the method is one solution, which I wanted to avoid.
Please forgive the noob question. I don't understand this "self" stuff in relation to this:
from selenium.common.exceptions import NoSuchElementException
def is_element_present(self, how, what):
try:
self.driver.find_element(by=how, value=what)
except NoSuchElementException:
return False
return True
#### navigate to the web page with a bunch of code here, then continue
text_present = self.assertTrue(self.is_element_present(By.LINK_TEXT, "Click Here"))
When I run this, here's the error I get:
test_link = self.assertTrue(self.is_element_present(By.LINK_TEXT, "Click Here"))
NameError: name 'self' is not defined
I understand "self" is used by convention as the first argument in a function but I don't understand the error. How do I define self?
Edit 1: I stand corrected on where "self" is used by convention (see comments/answers below). However, I still don't know what I should be doing to satisfy the Python interpreter.
self is "used by convention as the first argument" in a method, which is associated with a class. self in this context represents the instance of the class that is calling the method. A function, however, is not associated with a class, and thus no initial self argument is required. This is one of the fundamental differences between functions and methods--methods are associated with a class, and are called as instanceOfClass.methodName(args), where functions simply exist in the namespace and are called as functionName(args). Also note that when calling a method, self is not passed to the call: it is only used when defining the method.
You might know about the this pointer in C++. In priciple, Python's self is quite similar (but is more a reference than a pointer). It is the current object you apply the function to.
class MyClass:
def my_method(self, arg):
pass
my_object = MyClass()
my_object.my__method("whatever")
is actually like (not exactly identical to):
def my_func(the_object, arg):
pass
class MyClass:
pass
my_object = MyClass()
my_func(my_object, "whatever")
As there is actually more involved, the other way round will not work:
my_object.my_func("whatever")
Will raise an exception (an error), just try it. That is because my_func is an unbound function (not related to any object/class). my_method actually is bound (to my_object).
While this is passed implicitly (you do not have to specify it as an argument) to a method in C++, Python requires it to be listed explicitly as the first argument. The name self is actually just convention, a method will always get its object as the first argument, so it could also be named "thats_me". However, stick to `self', as many tools rely on this (syntax highlighting editors, debuggers, ...).
In the method itself, all members of the object are then accessed explicitly by self.my_member or self.my_func(). While in C++ one would writemy_memberorthis->my_member`, etcetera. The latter is basically similar to Python's way.
Please read more here and in the tutorial in general.
Background: Passing the object expliticly as the first argument is due to one of Pythons major guidelines: "explicit is better than implicit".
I was sure that there'd be an answer to this question somewhere on stack overflow, but I haven't been able to find one; most of them are in regards to passing functions, and not methods, as arguments to functions.
I'm currently working with Python 2.7.5 and I'm trying to define a function like this:
def func(object, method):
object.method()
that when called like so:
some_object_instance = SomeObject()
func(some_object_instance, SomeObject.some_object_method)
using a class defined like this:
class SomeObject:
def some_object_method(self):
# do something
is basically equivalent to doing this:
some_object_instance.some_object_method()
I, however, keep getting an attribute error--something along the lines of
'SomeObject' has no attribute 'method'
I was under the impression that I could legally pass methods as arguments and have them evaluate correctly when used in the aforementioned manner. What am I missing?
That's not the way method calling works. The foo.bar syntax looks for a method named bar on the foo object. If you already have the method, just call it:
def func(object, method):
method(object)
func(some_object_instance, SomeObject.some_object_method)
SomeObject.some_object_method is what's called an "unbound method": it's a method object without a self bound into it, so you have to explicitly pass the self to it.
This might make more sense with a concrete example:
>>> s = 'ABC'
>>> s_lower = s.lower # bound method
>>> s_lower()
'abc'
>>> str_lower = str.lower # unbound method
>>> str_lower(s)
'abc'
By comparison, some_object_instance.some_object_method is a "bound method", you can just call it as-is, and some_object_instance is already "bound in" as the self argument:
def func2(method):
method()
func2(some_object_instance.some_object_method)
Unbound methods aren't explained in detail the tutorial; they're covered in the section on bound methods. So you have to go to the reference manual for documentation (in [standard type hierarchy] (https://docs.python.org/2/reference/datamodel.html#the-standard-type-hierarchy), way down in the subsection "User-defined methods"), which can be a little bit daunting for novices.
Personally, I didn't really get this until I learned how it worked under the covers. About a year ago, I wrote a blog post How methods work to try to explain it to someone else (but in Python 3.x terms, which is slightly different); it may help. To really get it, you have to get through the Descriptor HOWTO, which may take a few read-throughs and a lot of playing around in the interactive interpreter before it really clicks, but hopefully you can understand the basic concepts behind methods before getting to that point.
Since you are passing an unbound method to the function, you need to call it as:
method(object)
Or better pass the name of the method as string and then use getattr:
getattr(object, method)()
While programming with python I am often confused with the following ambiguity:
should it be: function(a) or a.function(). Although the question is too general and can someone tell me which situation happens when?
Your confusion potentially stems from how python defines instance methods...
class Person
def speak(self, message):
print message
Looking at that definition I can see how someone would think you have to pass a Person as the first argument.
but it is just python's way to make self, the current instance of the person, available to the method.
so the proper way would be
person_instance = Person()
person_instance.speak("This is a message")
When you call it like a.function() you are calling a method named "function" from the object named "a".
If you don't know the difference between a method and a function/procedure, you need to study Object Oriented Programming concepts.