How to get parameter names in python format function? - python-3.x

func = "Hello {name}. how are you doing {time}!".format
For example, let's assume func is defined as above.
we don't have a definition of func at hand but we have an instance of it.
how can I get all arguments to this function?
apparently inspect.getargspec(func) does not work here!
if I just run this with empty parameters it returns an error with one missing parameter at a time, but I don't know how to get them directly:
a()
-------
KeyError Traceback (most recent call last)
<ipython-input-228-8d7b4527e81d> in <module>
----> 1 a()
KeyError: 'name'

what exactly are you trying to do? what is your expected output? as far as i know, there is no possibility to insert name and time, after you define func. because "string".format("call variables") <---- it cant call variables that are not defined. As far as i know the calling process happens first, independent of the formatting type. (f string, %, .format().. whatever you use)

Related

How do I return a value of a function in python

I'm trying to return the result of an operation in a function but I can't, I'm very sure the error it's pretty clear but I can't see it and I think this is the normal structure to make a return on a function.
This is the code:
#coding=utf-8
def sum_function(num1, num2):
result=num1+num2
return result
num_1=int(input("Please type a number: "))
num_2=int(input("Please type another number: "))
sum_function(num_1, num_2)
print(result)
This is the script running:
Please type a number: 1
Please type another number: 2
This is the error:
Traceback (most recent call last):
File "functions_practice.py", line 13, in <module>
print(result)
NameError: name 'result' is not defined
shell returned 1
I've seen some videos and blogs but I still don't understand.
everything you have is correct except for one small thing. When you define a function and want to get something back as a return value, you need to set a variable in your main code equal to the function call. Think of it like the function itself being a variable. For example:
function_result = sum_function(num1, num2)
when you declare this, whatever the value is you want to return from "sum_function(num1, num2)" will be passed into the new variable "function_result".
You are then able to use "function_result" to print, or manipulate however you like!
So, your solution would look like this:
def sum_function(num1, num2):
result=num1+num2
return result
num_1=int(input("Please type a number: "))
num_2=int(input("Please type another number: "))
function_result = sum_function(num_1, num_2)
print(function_result)
Your issue is that "result" is a local variable. You can only access it from within the sum_function function. If you want to print the result, try print(sum_function(num1, num2)).
The variable "result" is a local variable and it can be used just inside the function sum_function()

Get method's name using __getattribute__ without type error

I'm trying to print method's name using __getattribute__
but I get typeerror everytime I called the method, and the method is not excuted, is there anyway to get rid of the type error and have the method excuted ?
class Person(object):
def __init__(self):
super()
def test(self):
print(1)
def __getattribute__(self, attr):
print(attr)
p = Person()
p.test()
The above code gives the error
test
Traceback (most recent call last):
File "test1.py", line 15, in <module>
p.test()
TypeError: 'NoneType' object is not callable
Is there anyway to print the method's name only without giving the error ?
I tried to catch typeError inside __getattribute__ method, but it doesn't work
Another question is, why it says None Type object is not callable here
Thank you !
Ps. I know I can catch the error when I call the method, I mean is there anyway to deal this error inside __getattribute method? since my goal is to print method's name everytime a method is called
Answering your second question first, why is it saying NoneType not callable.
When you call p.test() Python tries to lookup the test attribute of the p instance. It calls the __getattribute__ method that you've overridden which prints 'test' and then returns. Because you're not returning anything it implicitly returns None. p.test is therefore None and calling it gives the error you get.
So how do we fix this? Once you've printed the attribute name, you need to return the attribute you're after. You can't just call getattr(self, attr) or you'll end up in an infinite loop so you have to call the method that would have been called if you hadn't overridden it.
def __getattribute__(self, attr):
print(attr)
return super().__getattribute__(attr) # calls the original method

Why setting attributes of class object instances results in AttributeError?

Why the following code produces an error
>>> object().foo = 'bar'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'foo'
while the next one works fine?
class A():
pass
A().foo = 'bar'
What is the exact difference between A and object? I believe o().foo = 'bar' leads to setattr('o', 'foo', 'bar') and this in turn results in o.__setattr__('foo', 'bar'). One would expect them to have identic __setattr__ methods since no overriding happens. Yet the outputs are different. Please explain why. What happens behind the scenes?
A similar pattern can be noticed for built-in functions and user-defined ones. I can't set my own attributes for let's say dict but it's perfectly ok to write (lambda:None).foo = 'bar'. What's going on here?

what are the use cases of type() function in python? specifically when i passed 3 arguments to it

I was studying python's type() function.
Its first application is to return the type of any python's object as follows:-
a = 5
type(a)
But in documentation there is another way of calling type() function by passing it three arguments as follows :-
X = type('X', (object,), dict(a=1))
This second call returning "type" class's object.
What are some use cases of this "type" class object?
Pleas elaborate.
Here is the documentation link, which i have followed, but could not get any help regarding it's use cases
Programiz's link, I have explored that as well, but unable to find any relevant stuff there as well
We use three arguments to create a new class.
The first argument is the class name that we are inheriting from. The second argument is the bases attribute (tuple containing all the base class) and in the third argument, we provide all declarations made in the class.
Now with an example,
>>> class X:
a = 1
>>> Y = type('X', (object,), dict(a=10))
Here, 'Y' inherits from class 'X'.
The second argument only means that the object we are creating is of 'object' type.
The third argument is just declaration of definitions that were made in class 'X'. If you don't mention anything inside dict(), then there will be no new attribute in class 'Y'.
>>> Y = type('X', (object,), dict())
Now if you try,
>>> Y.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'X' has no attribute 'a'
Go through this to understand the predefined attributes in Python.

How can I use pytest.raises with multiple exceptions?

I'm testing code where one of two exceptions can be raised: MachineError or NotImplementedError. I would like to use pytest.raises to make sure that at least one of them is raised when I run my test code, but it only seems to accept one exception type as an argument.
This is the signature for pytest.raises:
raises(expected_exception, *args, **kwargs)
I tried using the or keyword inside a context manager:
with pytest.raises(MachineError) or pytest.raises(NotImplementedError):
verb = Verb("donner<IND><FUT><REL><SG><1>")
verb.conjugate()
but I assume this only checks whether the first pytest.raises is None and sets the second one as the context manager if it is.
Passing multiple exceptions as positional arguments doesn't work, because pytest.raises takes its second argument to be a callable. Every subsequent positional argument is passed as an argument to that callable.
From the documentation:
>>> raises(ZeroDivisionError, lambda: 1/0)
<ExceptionInfo ...>
>>> def f(x): return 1/x
...
>>> raises(ZeroDivisionError, f, 0)
<ExceptionInfo ...>
>>> raises(ZeroDivisionError, f, x=0)
<ExceptionInfo ...>
Passing the exceptions as a list doesn't work either:
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
with pytest.raises([MachineError, NotImplementedError]):
File "/usr/local/lib/python3.4/dist-packages/_pytest/python.py", line 1290, in raises
raise TypeError(msg % type(expected_exception))
TypeError: exceptions must be old-style classes or derived from BaseException, not <class 'list'>
Is there a workaround for this? It doesn't have to use a context manager.
Pass the exceptions as a tuple to raises:
with pytest.raises( (MachineError, NotImplementedError) ):
verb = ...
In the source for pytest, pytest.raises may:
catch expected_exception; or
pass expected_exception to a RaisesContext instance, which then uses issubclass to check whether the exception was one you wanted.
In Python 3, except statements can take a tuple of exceptions. The issubclass function can also take a tuple. Therefore, using a tuple should be acceptable in either situation.

Resources