Reputation: 546
import sys
def attrs_and_types(mod_name):
print('Attributes and their types for module {}:'.format(mod_name))
print()
for num , attr in enumerate(dir(eval(mod_name))):
print("{idx}: {nam:30} {typ}".format(
idx=str(num + 1).rjust(4),
nam=(mod_name + '.' + attr).ljust(30),
typ=type(eval(mod_name + '.' + attr))))
attrs_and_types(sys.__name__)
Can anyone help me with these two lines?
for num, attr in enumerate(dir(eval(mod_name))):
attrs_and_types(sys.__name__)
I don't understand why sys.__name__
is passed as an argument to the function. It's supposed to be the name of the module. Why is .__name__
added to sys
?
And in the for
loop num, attr
is checking in this:
enumerate(dir(eval(mod_name)))
What is this? Is it a memory location?
Upvotes: 1
Views: 131
Reputation: 160447
Why is
.__name__
added to sys?
Every module has a __name__
attribute attached to it that has its name. It's just how things are.
What is this? Is it a memory location?
Nope, the author decided to use eval
(for some reason) to evaluate the string passed (sys.__name__
) and get back the module object. I cannot see why he decided to do so, it is quite dangerous to allow the function to receive an arg which you then pass to eval
, so don't do this.
A better implementation for this (without using the inspect
module) would look like this:
import sys
def attrs_and_types(mod):
name = mod.__name__
print('Attributes and their types for module {}:\n'.format(name))
fmt = "{idx}: {nam:30} {typ}"
for num , attr in enumerate(dir(sys)):
s = fmt.format(
idx=str(num + 1).rjust(4),
nam=(name + '.' + attr).ljust(30),
typ=type(attr)
)
print(s)
attrs_and_types(sys)
eval
isn't required if you just pass the module object directly. Even if you did pass the __name__
though, you'd still be able to get back the module via sys.modules
in a safer manner.
Upvotes: 1