Q:

Built-in function to read __slots__

Let's say I have a class like this:
class Test(object):
    prop = property(lambda self: "property")

The descriptor takes priority whenever I try to access Test().prop. So that will return 'property'. If I want to access the object's instance storage, I can do:
x = Test()
x.__dict__["prop"] = 12
print(x.__dict__["prop"])

However if I change my class to:
class Test(object):
    __slots__ = ("prop",)
    prop = property(lambda self: "property")

How do I do the same, and access the internal storage of x, to write 12 and read it back, since x.__dict__ no longer exist?
I am fairly new with Python, but I understand the Python philosophy is to give complete control, so why is an implementation detail preventing me from doing that?
Isn't Python missing a built-in function that could read from an instance internal storage, something like:
instance_vars(x)["prop"] = 12
print(instance_vars(x)["prop"])

which would work like vars, except it also works with __slots__, and with built-in types that don't have a __dict__?

A:

Short answer, You can't
The problem is that slots are themselves implemented in terms of descriptors.  Given:
class Test(object):
    __slots__ = ("prop",)

t = Test()

the phrase:
t.prop

Is translated, approximately to:
Test.prop.__get__(t, Test)

where Test.prop is a <type 'member_descriptor'> crafted by the run-time specifically to load prop values out of Test instances from their reserved space.
If you add another descriptor to the class body definition, it masks out the member_descriptor that would let you get to the slotted attribute; there's no way to ask for it, it's just not there anymore.  It's effectively like saying:
class Test(object):
    @property
    def prop(self):
        return self.__dict__['prop']

    @property
    def prop(self):
        return "property"

You've defined it twice.  there's no way to "get at" the first prop definition.

but:
Long answer, you can't in a general way. You can 
You can still abuse the python type system to get at it using another class definition.  You can change the type of a python object, so long as it has the exact same class layout, which roughly means that it has all of the same slots:
>>> class Test1(object):
...     __slots__ = ["prop"]
...     prop = property(lambda self: "property")
... 
>>> class Test2(object):
...     __slots__ = ["prop"]
... 
>>> t = Test1()
>>> t.prop
'property'
>>> t.__class__ = Test2
>>> t.prop = 5
>>> t.prop
5
>>> t.__class__ = Test1
>>> t.prop
'property'

But there's no general way to introspect an instance to work out its class layout; you just have to know from context.  You could look at it's __slots__ class attribute, but that won't tell you about the slots provided in the superclass (if any) nor will it give you any hint if that attribute has changed for some reason after the class was defined.

