Python question about overridden/redifined imported function as Class method
Question:
In https://github.com/biopython/biopython/blob/518c4be6ae16f1e00bfd55781171da91282b340a/Bio/SeqUtils/ProtParam.py I have this importing statement:
from Bio.SeqUtils import molecular_weight
and then in a Class:
class ProteinAnalysis:
.....
.....
def molecular_weight(self):
"""Calculate MW from Protein sequence."""
return molecular_weight(
self.sequence, seq_type="protein", monoisotopic=self.monoisotopic
)
......
......
What is this type of coding called? Is it normal to call imported function and class method with same name?
To my knowledge, self.molecular_weights
is not equal to molecular_weights
, but why call them the same? Is that PEP 8 compliant?
Would
a = ProteinAnalysis()
print(a.molecular_weights == molecular_weights)
give True
or False
?
What about:
print(a.molecular_weights(*args,**kwargs) == molecular_weights(*args, **kwargs))
Answers:
"What is this type of coding called"
This appears to simply be an API decision. I don’t know if there is a special name for it or not.
"Is it normal to call imported function and class method with same name?"
"normal" isn’t exactly a well defined, so instead I will suggest there is nothing unusual about it.
"To my knowledge, self.molecular_weights is not equal to molecular_weights, but why call them the same?"
When supplying the same parameters to the molecular_weights
function, the result will be the same value. And as mentioned earlier this is what was decided when building the API.
"Is that PEP 8 compliant?"
Probably.
"would molecular_weights == a.molecular_weights
be True"
No
"would molecular_weights() == a.molecular_weights()
be True"
No, molecular_weights has required parameters so this would raise and exception.
But this would return true:
molecular_weights(a.sequence, seq_type="protein", monoisotopic=a.monoisotopic) == a.molecular_weights()
Whoever wrote the code wanted the ProteinAnalaysis instances to have the molecular_weight function as part of its method API.
Yes. This is normal as there is no contradiction. You cannot freely get access to any class attributes even in methods inside a class. For example, let’s look at this:
var = 5
class SomeClass:
var = 6
def show(self):
print(var)
SomeClass().show()
The result is 5
. As there is only one "variable" var
in global scope.
If we unlink it via del var
, we will get NameError
:
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Input In [38], in <cell line: 1>()
----> 1 SomeClass.show()
Input In [37], in SomeClass.show()
5 def show():
----> 6 print(var)
NameError: name 'var' is not defined
But you can get free access during the class initialisation:
class SomeClass:
var = 6
print(var)
def show():
print(var)
Hereinabove code prints 6
.
In Biopython code only the imported function is used because the calling is inside a method where there is no direct access to the class attributes. Moreover, the method even is not initialised at the moment.
a.molecular_weights == molecular_weights
gives False
because even if they do the same they are different objects: a method & a function.
molecular_weights() == a.molecular_weights()
would give True
, if the same arguments are sent.
There is no contradiction with PEP8 naming rules as both do the same but one is a function, other is a method of appropriate class and objects.
this is an example I made to answer my question above:
in a folder named modul
I have __init__.py
:
#!/usr/bin/env python3
def pippo():
print('pippo')
return 5
in the same dir where modul
folder is , I have run.py
from modul import pippo
print(pippo, type(pippo))
class pluto():
print(pippo, type(pippo))
def pippo(self):
print('redifined')
print(pippo, type(pippo))
return pippo()
a = pluto()
a.pippo()
print('a.pippo() ---> ', a.pippo(), type(a.pippo))
print('fun == : ',a.pippo == pippo)
print('fun() == : ', a.pippo() == pippo())
print('type(fun) == : ', type(a.pippo) == type(pippo))
print('type == : ' , type(a.pippo) , type(pippo),' == : ', type(a.pippo) == type(pippo))
print('id : ', id(a.pippo) , id(pippo), ' id : ', id(a.pippo) == id(pippo))
result:
<function pippo at 0x7fcaa27a30d0> <class 'function'>
<function pippo at 0x7fcaa27a30d0> <class 'function'>
redifined
<function pippo at 0x7fcaa27a30d0> <class 'function'>
pippo
redifined
<function pippo at 0x7fcaa27a30d0> <class 'function'>
pippo
a.pippo() ---> 5 <class 'method'>
fun == : False
redifined
<function pippo at 0x7fcaa27a30d0> <class 'function'>
pippo
pippo
fun() == : True
type(fun) == : False
type == : <class 'method'> <class 'function'> == : False
id : 140508326858176 140508286038224 id : False
of course in my question molecular_weights
needed *args, **kwargs while my example show a function that just return an int
So again to me its like the imported function is returned loaded with class attributes, and I get that point, but why calling the method that returned that with same name ?
In https://github.com/biopython/biopython/blob/518c4be6ae16f1e00bfd55781171da91282b340a/Bio/SeqUtils/ProtParam.py I have this importing statement:
from Bio.SeqUtils import molecular_weight
and then in a Class:
class ProteinAnalysis:
.....
.....
def molecular_weight(self):
"""Calculate MW from Protein sequence."""
return molecular_weight(
self.sequence, seq_type="protein", monoisotopic=self.monoisotopic
)
......
......
What is this type of coding called? Is it normal to call imported function and class method with same name?
To my knowledge, self.molecular_weights
is not equal to molecular_weights
, but why call them the same? Is that PEP 8 compliant?
Would
a = ProteinAnalysis()
print(a.molecular_weights == molecular_weights)
give True
or False
?
What about:
print(a.molecular_weights(*args,**kwargs) == molecular_weights(*args, **kwargs))
"What is this type of coding called"
This appears to simply be an API decision. I don’t know if there is a special name for it or not.
"Is it normal to call imported function and class method with same name?"
"normal" isn’t exactly a well defined, so instead I will suggest there is nothing unusual about it.
"To my knowledge, self.molecular_weights is not equal to molecular_weights, but why call them the same?"
When supplying the same parameters to the molecular_weights
function, the result will be the same value. And as mentioned earlier this is what was decided when building the API.
"Is that PEP 8 compliant?"
Probably.
"would
molecular_weights == a.molecular_weights
be True"
No
"would
molecular_weights() == a.molecular_weights()
be True"
No, molecular_weights has required parameters so this would raise and exception.
But this would return true:
molecular_weights(a.sequence, seq_type="protein", monoisotopic=a.monoisotopic) == a.molecular_weights()
Whoever wrote the code wanted the ProteinAnalaysis instances to have the molecular_weight function as part of its method API.
Yes. This is normal as there is no contradiction. You cannot freely get access to any class attributes even in methods inside a class. For example, let’s look at this:
var = 5
class SomeClass:
var = 6
def show(self):
print(var)
SomeClass().show()
The result is 5
. As there is only one "variable" var
in global scope.
If we unlink it via del var
, we will get NameError
:
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Input In [38], in <cell line: 1>()
----> 1 SomeClass.show()
Input In [37], in SomeClass.show()
5 def show():
----> 6 print(var)
NameError: name 'var' is not defined
But you can get free access during the class initialisation:
class SomeClass:
var = 6
print(var)
def show():
print(var)
Hereinabove code prints 6
.
In Biopython code only the imported function is used because the calling is inside a method where there is no direct access to the class attributes. Moreover, the method even is not initialised at the moment.
a.molecular_weights == molecular_weights
gives False
because even if they do the same they are different objects: a method & a function.
molecular_weights() == a.molecular_weights()
would give True
, if the same arguments are sent.
There is no contradiction with PEP8 naming rules as both do the same but one is a function, other is a method of appropriate class and objects.
this is an example I made to answer my question above:
in a folder named modul
I have __init__.py
:
#!/usr/bin/env python3
def pippo():
print('pippo')
return 5
in the same dir where modul
folder is , I have run.py
from modul import pippo
print(pippo, type(pippo))
class pluto():
print(pippo, type(pippo))
def pippo(self):
print('redifined')
print(pippo, type(pippo))
return pippo()
a = pluto()
a.pippo()
print('a.pippo() ---> ', a.pippo(), type(a.pippo))
print('fun == : ',a.pippo == pippo)
print('fun() == : ', a.pippo() == pippo())
print('type(fun) == : ', type(a.pippo) == type(pippo))
print('type == : ' , type(a.pippo) , type(pippo),' == : ', type(a.pippo) == type(pippo))
print('id : ', id(a.pippo) , id(pippo), ' id : ', id(a.pippo) == id(pippo))
result:
<function pippo at 0x7fcaa27a30d0> <class 'function'>
<function pippo at 0x7fcaa27a30d0> <class 'function'>
redifined
<function pippo at 0x7fcaa27a30d0> <class 'function'>
pippo
redifined
<function pippo at 0x7fcaa27a30d0> <class 'function'>
pippo
a.pippo() ---> 5 <class 'method'>
fun == : False
redifined
<function pippo at 0x7fcaa27a30d0> <class 'function'>
pippo
pippo
fun() == : True
type(fun) == : False
type == : <class 'method'> <class 'function'> == : False
id : 140508326858176 140508286038224 id : False
of course in my question molecular_weights
needed *args, **kwargs while my example show a function that just return an int
So again to me its like the imported function is returned loaded with class attributes, and I get that point, but why calling the method that returned that with same name ?