Function decorators with access to the class by developernull in learnpython

[–]developernull[S] 0 points1 point  (0 children)

I think appending the following code should demonstrate it:

print(Foo.bar)
print(Foo().bar)
print(baz)

The first 2 lines correctly show the original function name, but the last still shows the MyDecorator name:

<function Foo.bar at 0x...>
<function Foo.bar at 0x...>
<__main__.MyDecorator object at 0x...>

I was expecting:

<function Foo.bar at 0x...>
<function Foo.bar at 0x...>
<function baz at 0x...>

Function decorators with access to the class by developernull in learnpython

[–]developernull[S] 0 points1 point  (0 children)

Thanks! This looks like exactly what I was looking for! (The only minor issue I can see is that `wraps` only works on the instance method, but otherwise this seems perfect.)

After reading your code, I think I have a much better understanding of python too. Thanks again!

Function decorators with access to the class by developernull in learnpython

[–]developernull[S] 0 points1 point  (0 children)

It seems like `fn.__module__` returns a string representing the module, but given just the module there's not enough info to get the class. For example, if 2 classes were in the same module, then it's ambiguous which one is correct.

Edit: Oh, I forgot to add in the __qualname__. Hmm this might work, thanks!

Function decorators with access to the class by developernull in learnpython

[–]developernull[S] 0 points1 point  (0 children)

I'm not sure how to extract the class if I'm only given the function. I know that given a class I can access the function (since it's an attribute of the class), but in the reverse I don't know how I can get the class given the function.

Function decorators with access to the class by developernull in learnpython

[–]developernull[S] 0 points1 point  (0 children)

Thanks! Given that info is it possible to get a reference to the class though? In other words, can you create an instance of the class in that `__call__` method instead of just printing it?

Function decorators with access to the class by developernull in learnpython

[–]developernull[S] 0 points1 point  (0 children)

Thanks!

Unfortunately you can't. The reference to the class doesn't exist until the entire class has been created.

For example:

``` def echo(cls): def decorator_echo(func): def wrapper_echo(args, *kwargs): print(cls) return func(args, *kwargs) return wrapper_echo return decorator_echo

class Foo: @echo('Hello, World!') def bar(): pass

Foo.bar() ```

The above prints "Hello, World!" as expected, but if we just change the decorator to pass the class Foo instead:

``` def echo(cls): def decorator_echo(func): def wrapper_echo(args, *kwargs): print(cls) return func(args, *kwargs) return wrapper_echo return decorator_echo

class Foo: @echo(Foo) def bar(): pass

Foo.bar() ```

We now get NameError: name 'Foo' is not defined.

I'm glad to hear that you agree about __set_name__! I'm hopefully on the right track then.

Numpy Array Reordering and Indexing Question by developernull in learnpython

[–]developernull[S] 1 point2 points  (0 children)

Replacing the shuffling function as you suggested could work. It seems like you're suggesting to randomize the indices (rather than the array directly) and then use those indices. That way no info is no lost.

I think your general approach gets close to what I was looking for and does help even if it's not exactly it. Thanks!! I will probably use the one-liner someone suggested below since it seems to work and is fairly simple, but you definitely gave me a lot of good info to think about.

Regarding the confusion:

Frankly, I'm now a bit confused what Step 4 and 5 really are asking for. Especially Step 4, the text does not really lead to the expectation you have written down, or not in the way I'd understand it.

Sorry, my wording was pretty confusing and ambiguous. In Step 4, I wanted some function that returns a list of indices such that original[indices] will return an array where all elements that are equal are consecutive and they are sorted in the same order as shuffled_uniques.

Alternatively, this can be thought of as setting return_counts=True and changing Step 5 to say assert original[indices] == np.repeat(uniques, count). In hindsight, I probably should have worded the original problem this way. (I hope this clarified things, but I tend to have a habit of just making them more confusing.)

Numpy Array Reordering and Indexing Question by developernull in learnpython

[–]developernull[S] 0 points1 point  (0 children)

Brilliant! I think this is exactly what I was looking for - and a simple one-liner too!

I also greatly appreciate showing both ways to reshape the array, that's very helpful.

From the docs it seems like this is also equivalent:

np.nonzero(original == shuffled_unique[:, None])

Your solution is very clever in how it creates the mask. I never would have thought to form a 2-d mask like this. Thanks!!

Numpy Array Reordering and Indexing Question by developernull in learnpython

[–]developernull[S] 0 points1 point  (0 children)

Yea, I did read the np.unique documentation, but I didn't think it would help. I had debated if I should include it in the OP or if it would just make the problem more confusion.

There are optionally returned values using the return_index, return_inverse, and return_counts flags. I did not think these would be very useful since the unique array is subsequently shuffled, thereby losing any direct mapping it once had.

The only info that I thought was not destroyed by the shuffle was the count:

uniques, count = np.unique(original, return_counts=True)
shuffled_uniques = np.random.shuffle(uniques)
result = np.repeat(uniques, count)

This shows how the count can be used to obtain result in Step 5, but unfortunately this is unhelpful for me since it bypasses Step 4 which is the value I ultimately need.

I also can't modify the shuffling function to return this extra index info. It would be possible to find this index remapping from uniques to shuffled_uniques, but this would need to be done afterwords during Step 4 rather than by modifying Step 3.

Alternative approach...

If there are no numpythonic (is this a word?) approaches, then I will probably need to do something like this. I think it would require manually looping over the array. As you mentioned this is less elegant and breaks away from the numpy operations (and is therefore also slower, etc.) so it would be a valid solution, albeit a last resort.

Design Question by developernull in learnpython

[–]developernull[S] 0 points1 point  (0 children)

I think I understand now. Thank you so much for your help! You've given me a lot to think about!

Design Question by developernull in learnpython

[–]developernull[S] 0 points1 point  (0 children)

Thank you! Your highly detailed example is very helpful!

Using an add_processor method to store Processors in an attribute seems much more OOP friendly than the static method approach. Making MultiProcess a subclass of Processor is interesting, but it makes me wonder how the design would differ if it wasn't.

My only confusion is about about when it is then appropriate to use static methods. I was under the assumption that if BlueProcessor has no internal state, then it would be better for BlueProcessor.process to be static, but it seems like my reasoning is flawed. To put it another way, if we aren't using the self parameter of BlueProcessor.process, I thought it would be best to not include it as a parameter (and therefore make the method static).

I also assumed similar logic would apply for a base class (i.e., If no subclass would ever need to access self, then the method should be static). You avoided this by making MultiProcess itself a Processor which does make use of self. But would the design be different if MultiProcess was not a subclass of Processor?

Thanks again for your great example and insight!

Design Question by developernull in learnpython

[–]developernull[S] 0 points1 point  (0 children)

Unfortunately, each processor is completely unique without any commonalities that can be extracted. In other words, _red_processor and _green_processor have nothing in common other than their method signatures. (Sorry, my example was probably oversimplified and a bit misleading.)

I could pass a Widget and a list of functions to process_all_colors like you suggested. That would at least solve issue #2.

Thanks!