3

If I have some code like this:

x.y.z = 12

I can infer that the z member is being indexed from the call to __setattr__. However if I have something like this:

foo = x.y.z # situation 1
bar = x.y.z.bar # situation 2

How can I determine which of the above situations I am in, if I care to do something special for z based on whether or not it is last in the chain of indexing? Is this kind of inference even possible in Python?

For more clarity let's assume I can change the implementation of all the objects being indexed, so using descriptors is wholly possible.

I worry that the answer to this question is "you can't do that" since it is impossible to override = like you can in C++.

Community
  • 1
  • 1
maxywb
  • 2,275
  • 1
  • 19
  • 25
  • 1
    you can overload `__get__` which will tell you when `something.z` is retrieved, and you can overload `__getattr__` (or `__getattribute__` if you need to override getting existing members) when getting a member of `z`, there is no special method for when it is the last one gotten though. – Tadhg McDonald-Jensen Jun 06 '16 at 14:16
  • 2
    Any way you can do it in python would mean that `foo.bar` would be the same as (or at least call the same magic methods) then `x.y.z.bar`, if you want to change what happens when just assigning to a variable then you are unfortunately out of luck. – Tadhg McDonald-Jensen Jun 06 '16 at 14:22

2 Answers2

1

I'm not sure how you define 'being last at chain of indexing'. You can still call more attributes on an object at any time.

But you can know when your object is being accessed as an attribute. As mentioned before, you can overload __getattr__ and __getattribute__, but a more robust way would be with descriptors.

This can get you started: http://nbviewer.jupyter.org/urls/gist.github.com/ChrisBeaumont/5758381/raw/descriptor_writeup.ipynb

Alternatively, there's a more formal guide: https://docs.python.org/3/howto/descriptor.html

thule
  • 4,034
  • 21
  • 31
  • This answer basically starts the OP on what could be a wild goose chase since it isn't clear what the OP's intentions are and a descriptor may not suite their needs, this would be a much better answer if you showcased some if the functionalities of descriptors and how to could relate to this use case. – Tadhg McDonald-Jensen Jun 06 '16 at 14:24
  • I disagree. Original question is pretty vague, hard to tell what the OP even tries to achieve. But if the intention is to mess with the way objects use attributes, that's what descriptors are for. – thule Jun 06 '16 at 14:28
  • I haven't had a chance to try a descriptor implementation, but I believe that's the right road to go down. – maxywb Jun 06 '16 at 14:29
  • "hard to tell what the OP even tries to achieve." exactly why just giving them a pointer may lead to them putting a lot of effort into learning about descriptors and then finding out that it doesn't suite their needs, I agree that it is likely the solution but I invite you to show an example of how a descriptor could achieve something like this. – Tadhg McDonald-Jensen Jun 06 '16 at 14:32
0

There is no way to do this with python overrides. The only way is to have a known member that means "the end." For example, if you wanted to know which member was being set in a long chain of indexes you'd need some kind of setter:

x.y.z.set(some_value)
maxywb
  • 2,275
  • 1
  • 19
  • 25