kjgregory
kjgregory

Reputation: 686

what is the python equivalent of "new" in C++

I'm trying to create a class that populates a list of structured data items along with some methods for populating the list from files and IO devices.

I'm having a problem with my method that fills out a new data structure and appends it to a list. It's set-up as a coroutine that fills up a temporary structure with data from the (yield) function. When it's done it appends the data to the list (e.g. self.list.append(newdata)). My problem is that this append happens by reference and I can't figure out how to initialize newdata to new memoryspace. What winds up happening is I have a list of data all pointing to the same data structure (e.g. "myclass.list[n] is myclass.list[m]" always yields TRUE). Can anyone tell me how to make this work?

If I were writing in C++, I would just need to do "newdata = new * mydatastructure;" after each loop iteration... I just can't figure out how to do this in python.... am I way off course here?

Upvotes: 3

Views: 4912

Answers (2)

2rs2ts
2rs2ts

Reputation: 11026

new is syntactic sugar for mydatastructure* = malloc(sizeof(mydatastructure)); (or something like that, it's been a while). It allocates the appropriate amount of memory on the heap for your what-have-you, and if you use the constructor (in C++) it initializes the memory.

Python takes care of this for you. Technically, there is a similar routine in Python, called __new__, which controls the allocation. But, you rarely need to override this on your objects.

The constructor for Python objects is called __init__. When you call __init__, __new__ is actually called first. So, when you construct objects in Python, you are automatically allocating new memory for them, and each one is different. As Benjamin pointed out, the constructor syntax (foo = Foo()) is the way you call __init__ without actually typing __init__().

Your problem lies elsewhere in your code, unfortunately.

By the way, if you really want to be sure that two variables reference the same object, you can use the id() function to get the reference number. The is keyword compares these reference numbers, in contrast to the == operator which uses the __eq__ method of objects to compare them.

Upvotes: 3

Jimmy Zelinskie
Jimmy Zelinskie

Reputation: 1575

My problem is that this append happens by reference and I can't figure out how to initialize newdata to new memoryspace.

If you're trying to append objects into a list by value, you might want to use something like copy.copy or copy.deepcopy to make sure what is being appended is copied.

>>> # The Problem
>>> class ComplexObject:
...     def __init__(self, herp, derp):
...         self.herp = herp
...         self.derp = derp
...
>>> obj = ComplexObject(1, 2)
>>> list = []
>>> list.append(obj)
>>> obj.derp = 5
>>> list[0].derp
5
>>> # obj and list[0] are the same thing in memory
>>> obj
<__main__.ComplexObject instance at 0x0000000002243D48>
>>> list[0]
<__main__.ComplexObject instance at 0x0000000002243D48>
>>> # The solution
>>> from copy import deepcopy
>>> list = []
>>> obj = ComplexObject(1,2)
>>> list.append(deepcopy(obj))
>>> obj.derp = 5
>>> list[0].derp
2
>>> obj
<__main__.ComplexObject instance at 0x0000000002243D48>
>>> list[0]
<__main__.ComplexObject instance at 0x000000000224ED88>

This is my attempt at actually solving your problem from your description without seeing any code. If you're more interested in allocation/constructors in Python, refer to another answer.

Upvotes: 2

Related Questions