Get all attributes of enclosing function - python-3.x

Given the following:
def outer(msg):
def inner():
print(msg)
return inner
returned_func = outer("Hello")
print(returned_func)
inner_func()
Returns the following:
<function outer.<locals>.inner at 0x7fe75ad9b670>
Hello
Questions:
Why when dir(outer) is called (see below), the inner function is missing?
How do I access inner as an attribute of outer?
I.e.
dir(outer)
['__annotations__',
'__call__',
'__class__',
'__closure__',
'__code__',
'__defaults__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__get__',
'__getattribute__',
'__globals__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__kwdefaults__',
'__le__',
'__lt__',
'__module__',
'__name__',
'__ne__',
'__new__',
'__qualname__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__']

Declaring a function inside of another function will not give you access to that function because the inner function is inside the local scope of the enclosing function. Think of it this way:
def foo():
n = 10
The function inner in your example is n in the example above. In Python, functions function a lot like variables. They can be passed around, returned, etc. In this example, do you think we should be able to access n by saying foo.n?
So why isn't it listed as an attribute of outer, (such as with class methods)?
This is totally different from a class declaration; instead, it is one example of higher order functions. It can be classified as such because one function returns another function.

When working with functions, you must set their attributes explicitely:
def outer():
def inner():
return "Hello"
# Define its attribute `inner`
outer.inner = inner
return inner() + " World"
print(outer()) # Outputs Hello World
print(outer.inner()) # Outputs Hello

Related

Why the function 'os.open(file_path, flag)' returns an integer?

I know I can use the function 'os.open' to deal with '.txt' files. But nevertheless I tried to open a '.jpg' file using this function as shown in the code below:
import os
f1 = os.open('imagem.jpg', os.O_RDONLY)
When I call f1 object to see what is inside it, python returns to me a integer that changes according to the number of times I have run the 'f1 = os.open('imagem.jpg', os.O_RDONLY)' code.
For example, the first time I run 'f1 = os.open('imagem.jpg', os.O_RDONLY)', f1 will assume 1, second time, 2, so on...
When I run the code below to see the methods and atributes of f1:
dir(f1)
python returns it to me:
['__abs__',
'__add__',
'__and__',
'__bool__',
'__ceil__',
'__class__',
'__delattr__',
'__dir__',
'__divmod__',
'__doc__',
'__eq__',
'__float__',
'__floor__',
'__floordiv__',
'__format__',
'__ge__',
'__getattribute__',
'__getnewargs__',
'__gt__',
'__hash__',
'__index__',
'__init__',
'__init_subclass__',
'__int__',
'__invert__',
'__le__',
'__lshift__',
'__lt__',
'__mod__',
'__mul__',
'__ne__',
'__neg__',
'__new__',
'__or__',
'__pos__',
'__pow__',
'__radd__',
'__rand__',
'__rdivmod__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__rfloordiv__',
'__rlshift__',
'__rmod__',
'__rmul__',
'__ror__',
'__round__',
'__rpow__',
'__rrshift__',
'__rshift__',
'__rsub__',
'__rtruediv__',
'__rxor__',
'__setattr__',
'__sizeof__',
'__str__',
'__sub__',
'__subclasshook__',
'__truediv__',
'__trunc__',
'__xor__',
'as_integer_ratio',
'bit_length',
'conjugate',
'denominator',
'from_bytes',
'imag',
'numerator',
'real',
'to_bytes']
Some one can explain to me what is happening?

How does one type hint a csv reader returned by csv.reader()?

How does one type hint a csv reader returned by csv.reader()?
When I check the type of the result in python I see:
>>> import csv
>>> with open('upt.csv', newline='') as csvfile:
... reader = csv.reader(csvfile, delimiter=' ', quotechar='|')
...
>>> reader
<_csv.reader object at 0x10c5292e0>
>>> type(reader)
<class '_csv.reader'>
>>> reader.__class__
<class '_csv.reader'>
>>> import _csv
>>> _csv.reader
<built-in function reader>
>>> _csv.reader.__class__
<class 'builtin_function_or_method'>
So it describes the class type of reader as _csv.reader but when I import _csv.reader that is not a class it is a function. How do I make a type hint for the csv.reader class instance?
The docs: https://docs.python.org/3/library/csv.html?highlight=csv#csv.reader
do not describe the return type using a class.
Oddly enough I do see class methods like __init__ and __new__ on the _csv.reader so maybe this is a c/c-binding issue?
>>> dir(_csv.reader) ['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__text_signature__']
Note:
DictReader does not have this problem:
>>> with open('upt.csv', newline='') as csvfile:
... dreader = csv.DictReader(csvfile)
...
>>> dreader
<csv.DictReader object at 0x10c410a30>
>>> csv.DictReader
<class 'csv.DictReader'>

datetime - a bug or a feature?

from datetime import datetime, timedelta
now = datetime.now()
then = datetime(2001, 1, 1)
delta = now-then
print(delta)
print(delta.days, delta.seconds)
print(delta.hours, delta.minutes)
gives the following errors:
6959 days, 16:09:27.863408
6959 58167
AttributeError: 'datetime.timedelta' object has no attribute 'hours'
AttributeError: 'datetime.timedelta' object has no attribute 'minutes'
is it a bug or a feature?
A feature: timedelta objects only have .days, .seconds, and .microseconds.
I suppose this is because days are sometimes irregular (e.g. due to leap seconds, and date arithmetic can account for that), while minutes and hours can be readily computed from seconds. Could have been slightly nicer, but still would have a few corner cases.
You can check all attributes in this way:
>>> dir(delta)
['__abs__', '__add__', '__bool__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__pos__', '__radd__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__rsub__', '__rtruediv__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', 'days', 'max', 'microseconds', 'min', 'resolution', 'seconds', 'total_seconds']
There are no "hours" and "minutes"

python: variables in a function with dot preceded by the function name

I need to understand this concept wherein we can use the dot (.) in the variable name within a function definition. There's no class definition nor a module here and Python is not supposed accept a variable name that includes a dot.
def f(x):
f.author = 'sunder'
f.language = 'Python'
print(x,f.author,f.language)
f(5)
`>>> 5 sunder Python`
Please explain how this is possible, and suggest related documentation for further exploration.
From official documentation:
Programmer’s note: Functions are first-class objects. A “def” statement executed inside a function definition defines a local function that can be returned or passed around. Free variables used in the nested function can access the local variables of the function containing the def.
So, function is an object:
>>> f.__class__
<class 'function'>
>>> f.__class__.__mro__
(<class 'function'>, <class 'object'>)
... and it means that it can store attributes:
>>> f.__dict__
{'language': 'Python', 'author': 'sunder'}
>>> dir(f)
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'author', 'language']

Python self keyword: advantages and drawbacks

What is the difference between these 2 classes (in terms of performance and design):
class A:
def methodA(self):
self.a=10
print(self.a)
And:
class B:
def methodB(self):
b=10
print(b)
b in the second example is local variable, not class-instance (or static class) variable, so with the first example you can do:
o = A()
o.methodA()
print(o.a)
With the second example this results into error and variable b runs out of scope after methodB() finishes.
About performance... By default instance variables are implemented via dictionary:
>>> class A(object):
... def __init__(self):
... self.a = 5
...
>>> o = A()
>>> dir(o)
['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__g
e__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__',
'__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '_
_setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a']
>>> o.__dict__
{'a': 5}
>>> o.__dict__.__class__
<class 'dict'>
So every access is basically like doing self.__dict__['a'], performance notes here.

Resources