2

What would be the Python equivalent of JavaScript's Object.create() functionality?

For example, in JS this is possible:

var s = { 'pots': 5, 'cups': 2 };
var t = Object.create( s );
console.log( t['pots'] );               // 5

t['pots'] = 9000;
console.log( t['pots'] );               // 9000
console.log( t['__proto__']['pots'] );  // 5, unchanged

s['pots'] = 33;
console.log( t['pots'] );               // 9000, unchanged
console.log( t['__proto__']['pots'] );  // 33

The closest thing I can think of is using copy:

s = { 'pots': 5, 'cups': 2 }
t = copy.copy( s )

It works, but it seems very wasteful to create a new copy of the reference object each time I want to inherit its properties.

Also I'm working with simple objects of the type seen above... not class instances.

1
  • There is no distinction between 'simple objects' and class instances - all objects behave in the same way. Python uses class-based inheritance not prototype based inheritance. Commented Feb 11, 2017 at 1:27

1 Answer 1

3

The dictionary class dict accepts another dictionary in its constructor.

s = { 'pots': 5, 'cups': 2 }
t = dict(s)

This is a shallow copy, which is fine when you're using immutable objects as values. (Keys must always be immutable types.) If you are using mutable containers such as other dictionaries (or lists, or various other types) as values, you should use copy.deepcopy().

It's important to note that in Python, items in a container (like a dict) and attributes on an object are different things entirely, accessed in different ways, and neither is exactly like a property in JavaScript. What you are actually trying to do is better accomplished by classes in Python:

class Thing(object):
    pots = 5
    cups = 2

s = Thing()
t = Thing()

In this case, s.pots accesses the value stored on the Thing class until you actually assign s.pots, at which point the instance's value of that attribute shadows the value stored on the class. So space is used on the instance only for attributes that have actually been assigned.

You can also define __slots__ on the class to allow only attributes of specific names to be assigned; this can reduce the memory overhead of instances, which is handy if you will be creating a lot of them.

The Python way of accessing attributes using a variable (or expression) rather than dot notation is the getattr() function. It is possible to create an object that can access the same data using either . or [], but it's trickier than you might expect to get it to work exactly like it does in JavaScript.

When you are using classes, the closest equivalent to your example (given an s, create a t with s's own attributes) is something like this:

t = type(s)()
t.__dict__.update(s.__dict__)

You could provide a method to do this:

class Cloneable(object):
    def clone(self):
        inst = type(self)()
        inst.__dict__.update(self.__dict__)
        return inst

Then derive Thing from Cloneable rather than object and you can do:

s = Thing()
t = s.clone()
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.