Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #21087 > unrolled thread
| Started by | Rolf Wester <rolf.wester@ilt.fraunhofer.de> |
|---|---|
| First post | 2012-03-01 14:07 +0100 |
| Last post | 2012-03-02 08:26 +0100 |
| Articles | 9 — 6 participants |
Back to article view | Back to comp.lang.python
exec Rolf Wester <rolf.wester@ilt.fraunhofer.de> - 2012-03-01 14:07 +0100
Re: exec Jean-Michel Pichavant <jeanmichel@sequans.com> - 2012-03-01 14:46 +0100
Re: exec Arnaud Delobelle <arnodel@gmail.com> - 2012-03-01 14:13 +0000
Re: exec Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-03-01 14:21 +0000
Re: exec Rolf Wester <rolf.wester@ilt.fraunhofer.de> - 2012-03-01 16:58 +0100
Re: exec Michael Ströder <michael@stroeder.com> - 2012-03-01 17:26 +0100
Re: exec Peter Otten <__peter__@web.de> - 2012-03-01 18:14 +0100
Re: exec Rolf Wester <rolf.wester@ilt.fraunhofer.de> - 2012-03-01 18:23 +0100
Re: exec Peter Otten <__peter__@web.de> - 2012-03-02 08:26 +0100
| From | Rolf Wester <rolf.wester@ilt.fraunhofer.de> |
|---|---|
| Date | 2012-03-01 14:07 +0100 |
| Subject | exec |
| Message-ID | <4f4f7527$1@news.fhg.de> |
Hi,
I would like to define methods using exec like this:
class A:
def __init__(self):
cmd = "def sqr(self, x):\n return x**2\nself.sqr = sqr\n"
exec cmd
a = A()
print a.sqr(a, 2)
This works, but I have to call sqr with a.sqr(a, 2), a.sqr(2) does not work
(TypeError: sqr() takes exactly 2 arguments (1 given)).
Is there a possibility to define methods using exec and getting normal behavior?
I would be very appreciative for any help.
With kind regards
Rolf Wester
[toc] | [next] | [standalone]
| From | Jean-Michel Pichavant <jeanmichel@sequans.com> |
|---|---|
| Date | 2012-03-01 14:46 +0100 |
| Message-ID | <mailman.320.1330609611.3037.python-list@python.org> |
| In reply to | #21087 |
Rolf Wester wrote: > Hi, > > I would like to define methods using exec like this: > > class A: > def __init__(self): > cmd = "def sqr(self, x):\n return x**2\nself.sqr = sqr\n" > exec cmd > a = A() > print a.sqr(a, 2) > > This works, but I have to call sqr with a.sqr(a, 2), a.sqr(2) does not work > (TypeError: sqr() takes exactly 2 arguments (1 given)). > > Is there a possibility to define methods using exec and getting normal behavior? > > I would be very appreciative for any help. > > With kind regards > Rolf Wester > > > I'll try to ignore you are using the exec statement which is an error :o) a.sqr(2) would have worked only if sqr was a *bound* method. print a.sqr <function sqr at 0x94ecd14> to oppose to print a.__init__ <bound method A.__init__ of <__main__.A instance at 0x948734c>> You cannot dynamically bind a method, however you can do the following. cmd = "def sqr(x):\n return x**2\nself.sqr = sqr\n" http://docs.python.org/reference/datamodel.html : <http://docs.python.org/reference/datamodel.html> "It is also important to note that user-defined functions which are attributes of a class instance are not converted bound methods; this only happens when the function is an attribute of the class. " JM
[toc] | [prev] | [next] | [standalone]
| From | Arnaud Delobelle <arnodel@gmail.com> |
|---|---|
| Date | 2012-03-01 14:13 +0000 |
| Message-ID | <mailman.322.1330611223.3037.python-list@python.org> |
| In reply to | #21087 |
On 1 March 2012 13:07, Rolf Wester <rolf.wester@ilt.fraunhofer.de> wrote: > Hi, > > I would like to define methods using exec like this: > > class A: > def __init__(self): > cmd = "def sqr(self, x):\n return x**2\nself.sqr = sqr\n" > exec cmd > a = A() > print a.sqr(a, 2) > > This works, but I have to call sqr with a.sqr(a, 2), a.sqr(2) does not work > (TypeError: sqr() takes exactly 2 arguments (1 given)). I'm curious to know your motivation for doing this. -- Arnaud
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2012-03-01 14:21 +0000 |
| Message-ID | <4f4f85eb$0$29989$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #21087 |
On Thu, 01 Mar 2012 14:07:15 +0100, Rolf Wester wrote:
> Hi,
>
> I would like to define methods using exec like this:
>
> class A:
> def __init__(self):
> cmd = "def sqr(self, x):\n return x**2\nself.sqr = sqr\n"
> exec cmd
> a = A()
> print a.sqr(a, 2)
That's... nasty, nasty code. I would hate to have to maintain that. I
hope you have a VERY good reason for doing it instead of the more obvious:
class B:
def __init__(self):
def sqr(self, x):
return x**2
self.sqr = sqr
or the even more obvious:
class C:
def sqr(self, x):
return x**2
And I *really* hope that you aren't getting the string to be exec'ed from
untrusted users. The world has enough code injection vulnerabilities.
If you don't understand what a code injection vulnerability is, or why
using exec on untrusted strings is dangerous, stop what you are doing and
don't write another line of code until you have read up it. You can start
here:
http://en.wikipedia.org/wiki/Code_injection
https://www.owasp.org/index.php/Injection_Flaws
and remember, code injection attacks are now the most frequent attack
vector of viruses, worms and malware, ahead of buffer overflow attacks.
Class C is, of course, the only one where a.sqr is an actual method, that
is, a.sqr(5) works instead of a.sqr(a, 5). You can fix this by doing one
of the following:
(1) Your function sqr() doesn't actually use self, so why require it? Get
rid of it!
class A:
def __init__(self):
# still nasty...
cmd = "def sqr(x):\n return x**2"
exec cmd
self.sqr = sqr # or put this in the cmd string (yuck)
class B:
def __init__(self):
# better, but still weird
def sqr(x):
return x**2
self.sqr = sqr
(2) Perhaps you actually do need access to self. So turn the function
into a proper method.
from types import MethodType
class A:
def __init__(self):
# still nasty...
cmd = "def sqr(self, x):\n return x**2\n"
exec cmd
self.sqr = MethodType(sqr, self)
class B:
def __init__(self):
def sqr(self, x):
return x**2
self.sqr = MethodType(sqr, self)
(3) My guess is that there is probably some sort of closure-based
solution that will work, or delegation, or composition. But given the toy
example you have shown, I don't know what that might be. If you explain
what you are actually doing, perhaps someone can suggest a better
solution.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Rolf Wester <rolf.wester@ilt.fraunhofer.de> |
|---|---|
| Date | 2012-03-01 16:58 +0100 |
| Message-ID | <4f4f9d55$1@news.fhg.de> |
| In reply to | #21087 |
Hi,
thanks for your replies so far.
The reason to use exec is just laziness. I have quite a lot of classes
representing material data and every class has a number of parameters.
The parameter are Magnitude objects (they have a value and a unit and overloaded
special functions to correctly handle the units). I want to have getter
functions that either return the Magnitude object or just the value:
iron = Iron()
iron.rho(0) => value
iron.rho() => Magnitude object
def rho(self, uf=1):
if uf == 1:
return self._rho
else:
return self._rho.val
And because this would mean quite a lot of writing I tried to do it with exec.
With kind regards
Rolf Wester
[toc] | [prev] | [next] | [standalone]
| From | Michael Ströder <michael@stroeder.com> |
|---|---|
| Date | 2012-03-01 17:26 +0100 |
| Message-ID | <jio7ur$ljn$1@dont-email.me> |
| In reply to | #21095 |
Rolf Wester wrote: > The reason to use exec is just laziness. The worst reason for using it. So I hope you carefully read Steven's comment and get rid of exec() for anything serious: <4f4f85eb$0$29989$c3e8da3$5496439d@news.astraweb.com> Ciao, Michael.
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2012-03-01 18:14 +0100 |
| Message-ID | <mailman.328.1330622109.3037.python-list@python.org> |
| In reply to | #21095 |
Rolf Wester wrote: > The reason to use exec is just laziness. I have quite a lot of classes > representing material data and every class has a number of parameters. > The parameter are Magnitude objects (they have a value and a unit and > overloaded special functions to correctly handle the units). I want to > have getter functions that either return the Magnitude object or just the > value: > > iron = Iron() > iron.rho(0) => value > iron.rho() => Magnitude object > > def rho(self, uf=1): > if uf == 1: > return self._rho > else: > return self._rho.val > > And because this would mean quite a lot of writing I tried to do it with > exec. Make the Magnitude class callable then: >>> class Magnitude(object): ... def __init__(self, value): ... self.value = value ... def __call__(self, uf=1): ... if uf == 1: ... return self ... return self.value ... >>> class Iron(object): ... def __init__(self): ... self.rho = Magnitude(42) ... >>> iron = Iron() >>> iron.rho() <__main__.Magnitude object at 0x7fb94062be10> >>> iron.rho(0) 42
[toc] | [prev] | [next] | [standalone]
| From | Rolf Wester <rolf.wester@ilt.fraunhofer.de> |
|---|---|
| Date | 2012-03-01 18:23 +0100 |
| Message-ID | <4f4fb151$1@news.fhg.de> |
| In reply to | #21098 |
Thank you, that really made things much easier and admittedly much less nasty too. Regards Rolf On 01/03/12 18:14, Peter Otten wrote: > Rolf Wester wrote: > >> The reason to use exec is just laziness. I have quite a lot of classes >> representing material data and every class has a number of parameters. >> The parameter are Magnitude objects (they have a value and a unit and >> overloaded special functions to correctly handle the units). I want to >> have getter functions that either return the Magnitude object or just the >> value: >> >> iron = Iron() >> iron.rho(0) => value >> iron.rho() => Magnitude object >> >> def rho(self, uf=1): >> if uf == 1: >> return self._rho >> else: >> return self._rho.val >> >> And because this would mean quite a lot of writing I tried to do it with >> exec. > > Make the Magnitude class callable then: > >>>> class Magnitude(object): > ... def __init__(self, value): > ... self.value = value > ... def __call__(self, uf=1): > ... if uf == 1: > ... return self > ... return self.value > ... >>>> class Iron(object): > ... def __init__(self): > ... self.rho = Magnitude(42) > ... >>>> iron = Iron() >>>> iron.rho() > <__main__.Magnitude object at 0x7fb94062be10> >>>> iron.rho(0) > 42 > >
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2012-03-02 08:26 +0100 |
| Message-ID | <mailman.343.1330673184.3037.python-list@python.org> |
| In reply to | #21095 |
Prasad, Ramit wrote: > Hi Peter, > > >>> class Magnitude(object): > > ... def __init__(self, value): > ... self.value = value > ... def __call__(self, uf=1): > ... if uf == 1: > ... return self > ... return self.value > ... > > >>> class Iron(object): > > ... def __init__(self): > ... self.rho = Magnitude(42) > ... > > > Why did you make uf=1 instead of None? > > ... def __call__(self, uf=None): > ... if uf is None: That's a design decision of the OP. I suggested an improvement of the implementation and left the interface alone.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web