How to print __init__ function arguments in python? - python-3.x

I am trying to create a dictionary of class names residing in module to their constructor args.
Constructor args should also be a dictionary where I will store the default values of the arguments wherever defined.
Any leads will be really helpful. Thanks in advance.
To provide more details about the use case, What I am trying to do here is for all the classes mentioned in the image image
I want to get the constructor parameters for e.g. please refer below image
image

If I understand you correctly, you just want the name of the parameters in the signature of your __init__.
That is actually quite simple using the inspect module:
Modern python answer:
import inspect
signature = inspect.signature(your_class.__init__).parameters
for name, parameter in signature.items():
print(name, parameter.default, parameter.annotation, parameter.kind)
Outdated answer
import inspect
signature = inspect.getargspec(your_class.__init__)
signature.args # All arguments explicitly named in the __init__ function
signature.defaults # Tuple containing all default arguments
signature.varargs # Name of the parameter that can take *args (or None)
signature.keywords # Name of the parameter that can take **kwargs (or None)
You can map the default arguments to the corresponding argument names like this:
argument_defaults = zip(signature.args[::-1], signature.defaults[::-1])

Most recently, the following works:
import inspect
signature = inspect.signature(yourclass.__init__)
for param in signature.parameters.values():
print(param)
The difference being (compared to the accepted answer), that the parameters instance variable needs to be accessed.

Related

How to force evaluation of type annotations from a different module?

I've been using Python's type annotations in an unusual way: I have some code that inspects the annotations of a function's arguments at run-time, searches for values that match the types of the arguments, and calls the function with values of appropriate types (if found).
This has been working wonderfully, and was remarkably easy to implement, but the source file has grown fairly large, so today I tried breaking it into multiple files. I found that get_type_hints() can't evaluate a type annotation if it's from a module other than the current one, at least not without being given a global namespace where all the needed types are defined.
I'm using from __future__ import annotations everywhere, so the type annotations in each function's .__annotations__ attribute are stored as strings in need of evaluation. To evaluate them, I need the globals from the module where the function was defined. How can I get that? Or will that even work? I'm using if TYPE_CHECKING: to avoid circular imports; consequently some annotations won't be available at run-time in each module where they're applied to a function.
Here's the code that extracts the types of the function arguments, if that helps:
def params_of(func: Callable) -> Iterable[Tuple[str, TypeAnnotation]]:
type_hints = get_type_hints(func)
for param_name in inspect.signature(func).parameters:
if param_name == 'return':
continue # disregard return type
yield (param_name, type_hints.get(param_name, Any))
(TypeAnnotation is only for readability; it's defined to Any.)

How to execute a code from another script and pass arguments

I have a python code try.py which has to execute another one called prova.py.
I do it as folows and it works:
exec(open("prova.py").read())
Now, I have some variables I need to pass to prova.py, and I did it as follows according to what found here: https://www.geeksforgeeks.org/exec-in-python/
var = {key:val for key, val in enumerate(lista_gp_todict)}
exec(open("prova.py").read(), var)
try.py does not give error which means the way I write exec now is still correct in terms of syntax, but in the moment this exec runs it gives error in prova.py:
NameError: name 'var' is not defined
which mean that the code prova.py which has inside the variable var does not recognise it, like it was not declared. In fact var is not declared into prova.py because if I pass it I assume it already there.
What am I doing wrong?
PS: my OS is windows
Typically you would call another script with the subprocess module.
subprocess.run() accepts an iterable of strings as arguments to be run as a separate process. You can use the arguments exactly as you would call them from command line.
subprocess.run(['python', 'prova.py', my_argument])
Since you wish to pass a dict to your script, you can do so by first serializing to json, which is just a nice way of saying "convert it to a string".
Since var is your dict you can do so like.
subprocess.run(['python', 'prova.py', json.dumps(var)])
And then deserialize or "convert back to a dict" in prova.py.
var = json.loads(sys.argv[1])
Alternatively, you could import prova.py if all you intend to use from it are functions, classes, or variables.
For example, if prova.py contains:
# prova.py
def my_func(var):
# do some stuff to var
You can then do this in your main script:
import prova
var = {key:val for key, val in enumerate(lista_gp_todict)}
prova.my_func(var)

python function parameter:complex parameter structure understanding

def resize_img( size: Tuple[int, int] = (299, 299)):
pass
What does the parameter mean?I did not find the docs.
In case you are asking about Tuple[int, int]: this syntax is provided by typing module. It helps you and other people reading your code to understand which type should parameters have when passed into function. In your example - if you try to pass something different than tuple of two ints (i.e. resize_img(5)) IDE will mark it as Expected type 'Tuple[int]', got 'int' instead. This does not break code execution, but shows developer that probably he/she uses this function with wrong type of parameter passed in.

Lambda commands for tracing tkinter variables [duplicate]

Python has classes for Tkinter variables StringVar(), BooleanVar(), etc. These all share the methods get(), set(string), and trace(mode, callback). The callback function passed as the second argument to trace(mode, callback) is passed four arguments, self, n, m, x.
For an example of a BooleanVar() these appear to be '', 'PYVAR0', 'w'.
The third argument x appears to be the mode that triggered the trace, in my case the variable was changed. However, what is the first variable that appears to be an empty string? What is the second, if I had to guess I'd say some internal name for the variable?
The first argument is the internal variable name. You can use this name as an argument to the tkinter getvar and setvar methods. If you give your variable a name (eg: StringVar(name='foo')) this will be the given name, otherwise it will be a name generated for you by tkinter (eg: PYVAR0)
If the first argument represents a list variable (highly unlikely in tkinter), the second argument will be an index into that list. If it is a scalar variable, the second argument will be the empty string.
The third argument is the operation, useful if you are using the same method for reading, writing and/or deleting the variable. This argument tells you which operation triggered the callback. It will be one of "read", "write", or "unset".
Tkinter is a python wrapper around a tcl/tk interpreter. The definitive documentation for variable traces can be found here: http://tcl.tk/man/tcl8.5/TclCmd/trace.htm#M14. Though, this only documents how the internal trace works, the tkinter wrapper sometimes massages the data.
The first argument is the name of the variable, but is not "useless" since you can set it when you declare the variable, e.g.:
someVar = IntVar(name="Name of someVar")
When you check the first argument in the trace callback it will equal "Name of someVar". Using the name to distinguish between variables, you can then bind the same handler to trace changes to any number of variables, rather than needing a separate handler for each variable.

Namedtuple Class Name

Just wondering that when we create a namedtuple object, why we always make the new object name (on the left) as the same as the namedtuple object name (on the right)?
I have tried an experiment to make them different names as below and then add in fields data using different objects name as below:
Running Code Example
>>> latlong = namedtuple('good', 'lat long')
>>> latlong(1, 2)
good(lat=1, long=2)
>>> good(1,2)
latlong(lat=1, long=2)
So when I add fields using latlong, it returns the good(), when I use good, it return latlong. Why they return different name each time? shouldn't them always return the the original object name which is good?
Thank You!
Erik
The name passed as first parameter is the one that gets stored inside the named tuple, as its __name__ attribute - and is used when you call repr on such a tuple. (You, or, in this case, the interactive interpreter - which makes a repr call to get you what you s printed).
The name you assign the namedtuple to - that is, the name on the left side of = is just any name you choose to use in your code - like you can name any other Python object.
You can even call a single namedtuple class a lot of names, by simply doing:
N = Name = NameAndAddress = namedtuple("NameAndAddress", "name address")
You can use the same object by using any of the assigned names. Or you can store a lot of namedtuples in a list, and give no explict name to any of them - just like any other object, what variable name holds a reference to an object makes no difference.
That is a bit unfortunate, because for better readability, we like to have the namedtuple "internal" name to be the same we use to reference it. Python, has no way of cleanly creating such an assignment - unless it is made inside a class body. In other words: there is no mechanism in the language that can make the expression on the right side of = to know which name it is being assigned to (on the left side of =) - so namedtuple signature requires you to explicitly type its name as a string. But despite that, there are no mechanisms or checks to verify if assigned and internal name are the same.
Just as a side comment: if you are assigning names inside a class body, there are mechanisms in Python that allow you to "tell" the assigned object its name (which will be a class attribute). Up to Python 3.5, you have to do that on the class's metaclass - or in a class decorator. In Python 3.6, the assigned object may be itself a descriptor, whose class implements a special method named __set_name__. If so, that method is called at class instantiation and passed the class object and the attribute name - the code in the method can then set the name in the instance.

Resources