6 kyu
A different kind of 'Lazy' function.
295Kacarott
Loading description...
Decorator
View
This comment has been reported as {{ abuseKindText }}.
Show
This comment has been hidden. You can view it now .
This comment can not be viewed.
- |
- Reply
- Edit
- View Solution
- Expand 1 Reply Expand {{ comments?.length }} replies
- Collapse
- Spoiler
- Remove
- Remove comment & replies
- Report
{{ fetchSolutionsError }}
-
-
Your rendered github-flavored markdown will appear here.
-
Label this discussion...
-
No Label
Keep the comment unlabeled if none of the below applies.
-
Issue
Use the issue label when reporting problems with the kata.
Be sure to explain the problem clearly and include the steps to reproduce. -
Suggestion
Use the suggestion label if you have feedback on how this kata can be improved.
-
Question
Use the question label if you have questions and/or need help solving the kata.
Don't forget to mention the language you're using, and mark as having spoiler if you include your solution.
-
No Label
- Cancel
Commenting is not allowed on this discussion
You cannot view this solution
There is no solution to show
Please sign in or sign up to leave a comment.
An underrated kata, it should be more popular, as it really makes your brains move a little.
Keep it up, I demand more decorator tasks, really like your kata series)
Learned a lot about decorators and arguments passed to wrapper (Thanks to Google!) . Thanks to you too!
My solution passed all tests (Passed: 307 / Failed: 4), except for the "Multiple lazy functions should work fine" block. Please tell me how it should look like?
That test checks if the functions are independant. It defines more than one lazy function, then calls them at intervals to make sure that each one is only affecting itself.
Example (not the real test):
Functions
a
andb
should each be on their own independant 'timers'.Thanks for the help friend, made it clear =)
Hello, I've been trying to pass the test cases however I'm facing some errors in the negative number situation.
For the input with @lazy(-2) and i = 2 and j = 5 (that is the 5th call) it is saying that it should be None. However, the following calls passed:
The next is the one that I described before, should it really be None? Since it the 1st call after a lazy call and n == -2
For
i=2, j=5
it should be a normal function (ie. 56). And the test case should support that. The asserted value is found withval = 56 if j%i else None
, which evaluates to 56.Could you post the solution you are trying to make work?
This comment has been hidden.
I think you agree it shouldn't do this:
[56, None, 56, 56, 56, 56, 56, 56, 56, 56]
I see it now, thanks to your comment I was able to come up with a solution that solved this kata, it is probably not the best solution but I will try to refactor and improve it. Thanks a lot!
It's great to see a decorator show up. I would appreciate more problems with python-specific language features instead of algorithms to which any language can be applied.
Aside from a small bit of syntax sugar, it's not very specific to python:
is equivalent to:
Suggestion: Maybe explicitly describe the requirement that when a function is currently "lazy", it is not to be run at all. This only becomes clear when the solution is subtely wrong (i.e. calls the decorated func regardless of laziness and only then decides what to return) and the test catches it (by having the decorated func have a side effect but not return anything itself). Requirements that only become clear during testing are a pet peeve of mine :-) In this case it was relatively harmless, but in other cases can require that an otherwise logically sound and functioning approach must be rewritten from scratch, throwing hours of work out the window.
I did try to explicitly state that:
When the lazy function 'does nothing', that means it simply immediately returns None.
.However on rereading, it is not a very clear sentence, so I'll try reword it to make it very clear.
Yes in the end I did recognize that this is what you meant by that statement, but only after my solution failed that particular test. In hindsight it's clear. Current description should work even for people like me :)
Not sure what that code is trying to test. It creates two variables
b
andc
, but assignment has nothing to do withlazy
this does not fire off any sort of event. Likewise, looking up a local variable (_a
) does not have any effect.b = _a
There for overall does nothing.c = dir(_a)
which should bedir(_a)
does do something if_a
happens to implement__dir__
but why would it ever? That's really really arbitrary. Can you show code that fails this test but passes the others? It is practically unfailable from what I can tell (aside from wrong answers but other tests cover that).something you could additionally test for is that the decorator is reusable, that is:
f and g should not be sharing state. Idk, maybe nobody cares and maybe it's difficult to explain what went wrong in error output.
this is a totally different requirement (and a misuse of decorators with arguments, unless clearly specified. And unless there is a very good reason, I'd still considere this a very bad idea)
I'd argue for it. I think this is reasonable to do. But I don't think it needs to be here. It could be, though. I'm mentioning the scenario.
That is, I argue that when you call
lazy
, you get a decorator back. And decorators should not share mutable state unless they specifically have that purpose.thing is, the only way I'd see a reasonnable scenario for this would be with the state being shared. Otherwise it looks like an antipattern.
BTW we may have arbitrary expressions in that
@syntax
(since 3.9? not sure)this is valid syntax:
I think that whatever that expression evaluates to THAT is the decorator, and each time the decorator is called, it should create new mutable state if it has any such.
besides, it has no business storing mutable state anywhere but within the scope that receives the function. one mutable state per function. (unless intended to share state, obviously)
I agree this might be a bit dangerous in general, but that's probably THEIR fault, it's not the "pattern" itself that is bad. Computing decorators/functions/classes is not weird, and only the final computed one should hold the mutable state.
(arguing because it's an interesting topic, not because I think it should be one way or another here :P I wonder if there's some authorative source to support either of us)
There's this wording here:
pep318 obviously not enough on its own, but it's some support. it's also ooold.
sure, but I don't see the link with the topic. => ?
without identifier, I strongly doubt it... => ?
I disagree because the decorator is already created at that point:
d=lazy(...)
. And so, it's the same decorator that is decorating the different functions and by essence, state that is created before the decorator function itself should be shared. Imo.But I see your point. Especially since we're already mutating state outside of the decorator function itself, here.
Tho, I feel like what you're describing is a supertask of the current one: creating a decorator factory function (the simplest way being to have one more layer, to separate the argument from the creation of the state)
(...that's effectively interesting to think about...)
:+1:
(I'm realizing that there is actually no need for another layer.... So you actually might even be right!)
So that's the difference in our perspective. I only consider the final value that is "passed" to
@
to be the decorator. Everything before that is just a function.it's valid syntax alright.
this word should not be allowed hissssss but yes. function. FUNCTION. and some definitions double as both. or rather, a decorator itself is just a function and calling it decorator as if though this was something special is imo really bad beacuse it makes them seem like difficult black magic when it's just... it's on the level of
map
andfilter
really. But these double definitions dispatch on callable (including classes)/other argument. Overloaded functions. Decorator is still the one that is finally passed the function.Sorry I don't mean to explain how things work XD trying to explain my perspective and why that makes me think decorators should behave this way.
typo? -> INvalid, you mean? Because my linter is crying, with this.
It would cry. That is trying to call
3
But it's valid syntax. It compiles. You don't get SyntaxError. You can have this in code that you run without exceptions, if you do not run this statement. You can't do that with invalid syntax in your file. This is a good valid program that runs without crashing:The point with it being that we can put an arbitrary expression there, and only the value that this expression evaluates to is the decorator.
Sorry about editing my post for 10 minutes. derp.
oh, I guess you meant that what was inside the parenthses would be a function, maybe? Well, I just got that:
Soooo, I'm not sure I'm following you.
Ye you are :D Missed one detail though. python 3.9+ Also, parens not required. These are good too:
Ah. right. So is this:
@1+2
. I parenthesized it because.. you need to do that when calling methods on int literals. But yeah no, don't need that here.oh, I'm an old guy (still 3.4.5... x) )
That's a good point. I was just trying to think of all edge cases to be thorough but those tests are most definitely unecessary. I'll remove for clarity.
could you please separate the 20 random tests wrapping them inside
@test.it
blocks?Yeah sure I'll do that now.
Done
Why for negative inputs the
n-th
,2n-th
,3n-th
etc. calls are lazy, but for positive inputs the1-st
,(n+1)-th
,(2n+1)-th
etc. calls are non-lazy?Because I want the first call of the function to always work. (Except for
n == -1
which is always lazy). From the perspective of trying to 'prank' someone, it is harder to detect and debug if the functions always initially work, but then break later. (Of course it's a weak example because decorators are pretty easy to spot, but that's the idea.)Is there any reason except "it makes sense with my backstory" why negative inputs should be a special case?
Positive inputs are also a special case. He's encoding both a boolean and a positive integral number into a single native signed integer.
I've seen worse.
Resolved I think.
This is my first Kata so if I have accidentally made a duplicate, or if there's anything to improve please let me know!