473,729 Members | 2,376 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

function parameter scope python 2.5.2


I recently encountered some interesting behaviour that looks like a bug
to me, but I can't find the appropriate reference to any specifications
to clarify whether it is a bug.

Here's the example code to demonstrate the issue:

class SomeObject(obje ct):

def __init__(self):
self.words = ['one', 'two', 'three', 'four', 'five']

def main(self):
recursive_func( self.words)
print self.words

def recursive_func( words):
if len(words) 0:
word = words.pop()
print "Popped: %s" % word
recursive_func( words)
else:
print "Done"

if __name__ == '__main__':
weird_obj = SomeObject()
weird_obj.main( )
The output is:

Popped: five
Popped: four
Popped: three
Popped: two
Popped: one
Done
[]

Of course I expected that recursive_func( ) would receive a copy of
weird_obj.words but it appears to happily modify the object.

Of course a work around is to explicitly create a copy of the object
property befor passing it to recursive_func, but if it's used more than
once inside various parts of the class that could get messy.

Any thoughts? Am I crazy and this is supposed to be the way python works?
Nov 20 '08 #1
11 1970
J Kenneth King <ja***@agentult ra.comwrites:
I recently encountered some interesting behaviour that looks like a bug
to me, but I can't find the appropriate reference to any specifications
to clarify whether it is a bug.

Here's the example code to demonstrate the issue:

class SomeObject(obje ct):

def __init__(self):
self.words = ['one', 'two', 'three', 'four', 'five']

def main(self):
recursive_func( self.words)
print self.words

def recursive_func( words):
if len(words) 0:
word = words.pop()
print "Popped: %s" % word
recursive_func( words)
else:
print "Done"

if __name__ == '__main__':
weird_obj = SomeObject()
weird_obj.main( )
The output is:

Popped: five
Popped: four
Popped: three
Popped: two
Popped: one
Done
[]

Of course I expected that recursive_func( ) would receive a copy of
weird_obj.words but it appears to happily modify the object.

Of course a work around is to explicitly create a copy of the object
property befor passing it to recursive_func, but if it's used more than
once inside various parts of the class that could get messy.

Any thoughts? Am I crazy and this is supposed to be the way python works?
Of course, providing a shallow (or deep as necessary) copy makes it
work, I'm curious as to why the value passed as a parameter to a
function outside the class is passed a reference rather than a copy.
Nov 20 '08 #2
On Nov 21, 9:40*am, J Kenneth King <ja...@agentult ra.comwrote:
Of course, providing a shallow (or deep as necessary) copy makes it
work, I'm curious as to why the value passed as a parameter to a
function outside the class is passed a reference rather than a copy.
You're passing neither a reference nor a copy, you're passing the
object (in this case a list) directly:

http://effbot.org/zone/call-by-object.htm
Nov 20 '08 #3
On Nov 20, 6:40*pm, J Kenneth King <ja...@agentult ra.comwrote:
J Kenneth King <ja...@agentult ra.comwrites:
I recently encountered some interesting behaviour that looks like a bug
to me, but I can't find the appropriate reference to any specifications
to clarify whether it is a bug.
Here's the example code to demonstrate the issue:
class SomeObject(obje ct):
* * def __init__(self):
* * * * self.words = ['one', 'two', 'three', 'four', 'five']
* * def main(self):
* * * * recursive_func( self.words)
* * * * print self.words
def recursive_func( words):
* * if len(words) 0:
* * * * word = words.pop()
* * * * print "Popped: %s" % word
* * * * recursive_func( words)
* * else:
* * * * print "Done"
if __name__ == '__main__':
* * weird_obj = SomeObject()
* * weird_obj.main( )
The output is:
Popped: five
Popped: four
Popped: three
Popped: two
Popped: one
Done
[]
Of course I expected that recursive_func( ) would receive a copy of
weird_obj.words but it appears to happily modify the object.
Of course a work around is to explicitly create a copy of the object
property befor passing it to recursive_func, but if it's used more than
once inside various parts of the class that could get messy.
Any thoughts? Am I crazy and this is supposed to be the way python works?

Of course, providing a shallow (or deep as necessary) copy makes it
work, I'm curious as to why the value passed as a parameter to a
function outside the class is passed a reference rather than a copy.
Why should it be a copy by default ? In Python all copies have to be
explicit.

George
Nov 21 '08 #4
On Nov 21, 6:31*am, J Kenneth King <ja...@agentult ra.comwrote:
I recently encountered some interesting behaviour that looks like a bug
to me, but I can't find the appropriate reference to any specifications
to clarify whether it is a bug.

Here's the example code to demonstrate the issue:

class SomeObject(obje ct):

* * def __init__(self):
* * * * self.words = ['one', 'two', 'three', 'four', 'five']

* * def main(self):
* * * * recursive_func( self.words)
* * * * print self.words

def recursive_func( words):
* * if len(words) 0:
* * * * word = words.pop()
* * * * print "Popped: %s" % word
* * * * recursive_func( words)
* * else:
* * * * print "Done"

if __name__ == '__main__':
* * weird_obj = SomeObject()
* * weird_obj.main( )

The output is:

Popped: five
Popped: four
Popped: three
Popped: two
Popped: one
Done
[]

Of course I expected that recursive_func( ) would receive a copy of
weird_obj.words but it appears to happily modify the object.

Of course a work around is to explicitly create a copy of the object
property befor passing it to recursive_func, but if it's used more than
once inside various parts of the class that could get messy.

Any thoughts? Am I crazy and this is supposed to be the way python works?
You are passing a mutable object. So it can be changed. If you want a
copy, use slice:
>>L = [1, 2, 3, 4, 5]
copy = L[:]
L.pop()
5
>>L
[1, 2, 3, 4]
>>copy
[1, 2, 3, 4, 5]

....in your code...

def main(self):
recursive_func( self.words[:])
print self.words

....or...
>>def recursive_func( words):
words = words[:]
if len(words) 0:
word = words.pop()
print "Popped: %s" % word
recursive_func( words)
else:
print "Done"

words = ["one", "two", "three"]
recursive_fun c(words)
Popped: three
Popped: two
Popped: one
Done
>>words
['one', 'two', 'three']

Though I haven't been doing this long enough to know if that last
example has any drawbacks.

If we knew more about what you are trying to do, perhaps an
alternative would be even better.

- Rafe
Nov 21 '08 #5
On Thu, 20 Nov 2008 18:31:12 -0500, J Kenneth King wrote:
Of course I expected that recursive_func( ) would receive a copy of
weird_obj.words but it appears to happily modify the object.
I am curious why you thought that. What made you think Python should/did
make a copy of weird_obj.words when you pass it to a function?

This is a serious question, I'm not trying to trap you into something :)
--
Steven
Nov 21 '08 #6
J Kenneth King <ja***@agentult ra.comwrites:
I recently encountered some interesting behaviour that looks like a bug
to me, but I can't find the appropriate reference to any specifications
to clarify whether it is a bug.

Here's the example code to demonstrate the issue:

class SomeObject(obje ct):

def __init__(self):
self.words = ['one', 'two', 'three', 'four', 'five']

def main(self):
recursive_func( self.words)
print self.words

def recursive_func( words):
if len(words) 0:
word = words.pop()
print "Popped: %s" % word
recursive_func( words)
else:
print "Done"

if __name__ == '__main__':
weird_obj = SomeObject()
weird_obj.main( )
The output is:

Popped: five
Popped: four
Popped: three
Popped: two
Popped: one
Done
[]

Of course I expected that recursive_func( ) would receive a copy of
weird_obj.words but it appears to happily modify the object.

Of course a work around is to explicitly create a copy of the object
property befor passing it to recursive_func, but if it's used more than
once inside various parts of the class that could get messy.

Any thoughts? Am I crazy and this is supposed to be the way python works?
That's because Python isn't call-by-value. Or it is according to some,
it's just that the values it passes are references. Which, according to
others, is unnecessarily convoluted: it's call-by-object, or shall we
call it call-by-sharing? At least everybody agrees it's not
call-by-reference or call-by-name.

There. I hope this helps!

--
Arnaud
Nov 21 '08 #7
alex23 <wu*****@gmail. comwrites:
On Nov 21, 9:40Â*am, J Kenneth King <ja...@agentult ra.comwrote:
>Of course, providing a shallow (or deep as necessary) copy makes it
work, I'm curious as to why the value passed as a parameter to a
function outside the class is passed a reference rather than a copy.

You're passing neither a reference nor a copy, you're passing the
object (in this case a list) directly:

http://effbot.org/zone/call-by-object.htm
Ah, thanks -- that's precisely what I was looking for.

I knew it couldn't be a mistake; I just couldn't find the documentation
on the behaviour since I didn't know what it was called in the python
world.

Cheers.
Nov 21 '08 #8
Steven D'Aprano <st***@REMOVE-THIS-cybersource.com .auwrites:
On Thu, 20 Nov 2008 18:31:12 -0500, J Kenneth King wrote:
>Of course I expected that recursive_func( ) would receive a copy of
weird_obj.word s but it appears to happily modify the object.

I am curious why you thought that. What made you think Python should/did
make a copy of weird_obj.words when you pass it to a function?

This is a serious question, I'm not trying to trap you into something :)
Don't worry, I don't feel "trapped" in usenet. ;)

It was more of an intuitive expectation than a suggestion that Python
got something wrong.

I was working on a program of some complexity recently and quickly
caught the issue in my tests. I knew what was going on and fixed it
expediently, but the behaviour confused me and I couldn't find any
technical documentation on it so I figured I just didn't know what it
was referred to in Python. Hence the post. :)

I suppose I have some functional sensibilities and assumed that an
object wouldn't let a non-member modify its properties even if they were
mutable.

Of course if there is any further reading on the subject, I'd appreciate
some links.

Cheers.
Nov 21 '08 #9
On Fri, 21 Nov 2008 10:12:08 -0500, J Kenneth King wrote:
Steven D'Aprano <st***@REMOVE-THIS-cybersource.com .auwrites:
>>
I am curious why you thought that. What made you think Python should/did
make a copy of weird_obj.words when you pass it to a function?
[snip]
Of course if there is any further reading on the subject, I'd appreciate
some links.
As one relatively new Python fan to another, I recommend following
this newsgroup. Many important aspects of Python that several books
failed to drive through my skull are very clearly (and repeatedly)
explained here. Hang around for a week, paying attention to posts
with subjects like "Error in Python subscripts" (made-up example),
and curse me if you don't find it greatly rewarding.

--
To email me, substitute nowhere->spamcop, invalid->net.
Nov 21 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
14943
by: domeceo | last post by:
can anyone tell me why I cannot pass values in a setTimeout function whenever I use this function it says "menu is undefined" after th alert. function imgOff(menu, num) { if (document.images) { document.images.src = eval("mt" +menu+ ".src") } alert("imgOff_hidemenu"); hideMenu=setTimeout('Hide(menu,num)',500);
20
1992
by: Gregory Piñero | last post by:
Hey guys, would someone mind giving me a quick rundown of how references work in Python when passing arguments into functions? The code below should highlight my specific confusion: <code> bool1=True lst1= def func1(arg1): arg1.append(4)
2
3001
by: FAN | last post by:
I want to define some function in python script dynamicly and call them later, but I get some problem. I have tried the following: ################################## # code ################################## class test: def __init__(self): exec("def dfunc(msg):\n\tprint msg\nprint 'exec def function'") dfunc('Msg in init ...') # it work
38
2772
by: Lasse Vågsæther Karlsen | last post by:
After working through a fair number of the challenges at www.mathschallenge.net, I noticed that some long-running functions can be helped *a lot* by caching their function results and retrieving from cache instead of calculating again. This means that often I can use a natural recursive implementation instead of unwinding the recursive calls to avoid big exponential running-times. Ok, so I thought, how about creating a decorator that...
5
1325
by: Martin Johansen | last post by:
Hello C programmers If I have a function, say void f(int a, char b); And I call this function with the following arguments char a; int b;
16
1653
by: Rob Somers | last post by:
Say I have the following code: void foo(int some_int); ..... int x = 5; foo(x); ..... void foo(int some_int) {
7
1875
by: Csaba Gabor | last post by:
I feel like it's the twilight zone here as several seemingly trivial questions are bugging me. The first of the following three lines is a syntax error, while the last one is the only one that shows the alert. What is the essential reason? function () { alert('hi mom'); }(); function () { alert('hi dad'); }(8); var x=function () { alert('hi bro'); }();
78
4951
by: Josiah Manson | last post by:
I found that I was repeating the same couple of lines over and over in a function and decided to split those lines into a nested function after copying one too many minor changes all over. The only problem is that my little helper function doesn't work! It claims that a variable doesn't exist. If I move the variable declaration, it finds the variable, but can't change it. Declaring the variable global in the nested function doesn't work...
4
2493
by: Tony Lownds | last post by:
(Note: PEPs in the 3xxx number range are intended for Python 3000) PEP: 3107 Title: Function Annotations Version: $Revision: 53169 $ Last-Modified: $Date: 2006-12-27 20:59:16 -0800 (Wed, 27 Dec 2006) $ Author: Collin Winter <collinw@gmail.com>, Tony Lownds <tony@lownds.com> Status: Draft Type: Standards Track
11
1595
by: =?iso-8859-1?q?Erik_Wikstr=F6m?= | last post by:
struct foo { int i; }; int bar(foo& f) { return f.i++; } int main() { bar(foo());
0
8917
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9426
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9281
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9200
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9142
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
4525
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3238
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2680
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2163
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.