Reading class method definition - what is Callable? - python-3.x

I am relatively new to python, and I started to read the docs when using packages, but I'm having a hard time understanding some of it:
post_to_main_thread(self: open3d.cpu.pybind.visualization.gui.Application, arg0: open3d::visualization::gui::Window, arg1: Callable[[], None]) → None
the only thing here that I don't understand is the arg1 with that callable, and I can't find an explanation on it at the web.

Interesting question!
So post_to_main_thread() is a method that takes 3 arguments (inputs/variables) and returns None.
Because it's a method (a function associated with a class, not just a standalone function) the first argument, self, refers to the instance of the class that the function is part of.
The other two arguments are passed within the function parentheses, as expected with a standalone function. So a call might look like this:
instance_name = open3d.visualization.gui.Application(...)
instance_name.post_to_main_thread(arg1, arg2)
arg1 should be of type open3d::visualization::gui::Window. This is an instance of the class open3d.visualization.gui.Window().
arg2 should be of type Callable(). This describes a number of built-ins that you can find details about in the documentation. To quote:
The subscription syntax must always be used with exactly two values: the argument list and the return type. The argument list must be a list of types or an ellipsis; the return type must be a single type.
So in this case the type should be Callable[[], None], which means this should be a function that takes no input and returns None. Carrying on from our previous example, you'd pass this as an argument like so:
def my_callable:
print('Hello, World!')
return
instance_name.post_to_main_thread(arg1, my_callable)
Does that clear things up?

Related

What does *[, keyword_arg = value] do in Python keyword only function definition?

Consider this:
help(min)
which gives:
Help on built-in function min in module builtins:
min(...)
min(iterable, *[, default=obj, key=func]) -> value
min(arg1, arg2, *args, *[, key=func]) -> value
With a single iterable argument, return its smallest item. The
default keyword-only argument specifies an object to return if
the provided iterable is empty.
With two or more arguments, return the smallest argument.
My question is what is the difference between:
min(iterable, *[, default=obj, key=func]) -> value
and
min(iterable, *, default=obj, key=func) -> value
The Python documentation/help derives from EBNF to describe grammar. A pair of [ ] means "optional" in EBNF and the Python documentation; for terseness, common symbols like ( ) and names are not quoted in the documentation even though this has different meaning in EBNF.
The * and , are derived from Python's call syntax. * means "end of positional parameters".
For the concrete example of
min(iterable, *[, default=obj, key=func]) -> value
this means default and key are optional keyword-only parameters.
This is not Python syntax, it is just used in the help text to show that those arguments are optional.

How to avoid casting arguments in Spock

I want to get a List from repository and assert its contents.
In following code I get a warning that states that Object cannot be assigned to List
Is there any way to add better argument to handle such case?
myDomainObjectRepository.save(_) >> { arguments ->
final List<MyDomainObject> myDomainObjects = arguments[0]
assert myDomainObjects == [new MyDomainObject(someId, someData)]
}
To elaborate on Opals answer: There are two parts and a footnote in the docs that are relevant here:
If the closure declares a single untyped parameter, it gets passed the
method’s argument list:
And
In most cases it would be more convenient to have direct access to the
method’s arguments. If the closure declares more than one parameter or
a single typed parameter, method arguments will be mapped one-by-one
to closure parameters[footnote]:
Footnote:
The destructuring semantics for closure arguments come straight from
Groovy.
The problem is that you have a single argument List, and since generics are erased groovy can't decide that you actually want to unwrap the list.
So a single non-List argument works fine:
myDomainObjectRepository.save(_) >> { MyDomainObject myDomainObject ->
assert myDomainObject == new MyDomainObject(someId, someData)
}
or a List argument combined with a second, e.g., save(List domain, boolean flush)
myDomainObjectRepository.save(_, _) >> { List<MyDomainObject> myDomainObjects, boolean flush ->
assert myDomainObjects == [new MyDomainObject(someId, someData)]
}
So the docs are a little bit misleading about this edge case. I'm afraid that you are stuck with casting for this case.
Edit: You should be able to get rid of the IDE warnings if you do this.
myDomainObjectRepository.save(_) >> { List<List<MyDomainObject>> arguments ->
List<MyDomainObject> myDomainObjects = arguments[0]
assert myDomainObjects == [new MyDomainObject(someId, someData)]
}
The docs seems to be precise:
If the closure declares a single untyped parameter, it gets passed the method’s argument list
However I've just changed my spec that uses rightShift + arguments to accept a single type argument and it did work. Try it out.

Can someone tell me the function of this "self"

I use python to insert data into MySQL, in some tutorial, I must include "self" on my function,
Def haha(self, hihi):
Print(hihi)
I have no idea what does it mean..
This function takes instance of itself as an argument. It is done when declaring methods of a class because function needs to run the method from its own particular instance. Also self needed to access or update fields of particular instance of a class. For example:
class A:
b = 3
def f(self):
self.b = 5
So when you create object of type A and call method f from this object, only this object's b will become 5, but other objects of type A will have b equaling to 3. Also, when you call method, you do not pass instance of it as an argument, and can just start passing arguments starting after 'self'.

Mypy reports an incompatible supertype error with overridden method

Below is a simplified example of a problem I've encountered with mypy.
The A.transform method takes an iterable of objects, transforms each one (defined in the subclass B, and potentially other subclasses) and returns an iterable of transformed objects.
from typing import Iterable, TypeVar
T = TypeVar('T')
class A:
def transform(self, x: Iterable[T]) -> Iterable[T]:
raise NotImplementedError()
class B(A):
def transform(self, x: Iterable[str]) -> Iterable[str]:
return [x.upper() for x in x]
However mypy says:
error: Argument 1 of "transform" incompatible with supertype "A"
error: Return type of "transform" incompatible with supertype "A"
If I remove [T] from A.transform(), then the error goes away. But that seems like the wrong solution.
After reading about covariance and contravariance, I thought that setting
T = TypeVar('T', covariant=True) might be a solution, but this produces the same error.
How can I fix this? I have considered binning the design altogether and replacing the A class with a higher order function.
Making T covariant or contravariant isn't really going to help you in this case. Suppose that the code you had in your question was allowed by mypy, and suppose a user wrote the following snippet of code:
def uses_a_or_subclass(foo: A) -> None:
# This is perfectly typesafe (though it'll crash at runtime)
print(a.transform(3))
# Uh-oh! B.transform expects a str, so we just broke typesafety!
uses_a_or_subclass(B())
The golden rule to remember is that when you need to overwrite or redefine a function (when subclassing, like you're doing, for example), that functions are contravariant in parameters, and covariant in their return type. This means that when you're redefining a function, it's legal to make the parameters more broad/a superclass of the original parameter type, but not a subtype.
One possible fix is to make your entire class generic with respect to T. Then, instead of subclassing A (which is now equivalent to subclassing A[Any] and is probably not what you want if you'd like to stay perfectly typesafe), you'd subclass A[str].
Now, your code is perfectly typesafe, and your redefined function respects function variance:
from typing import Iterable, TypeVar, Generic
T = TypeVar('T')
class A(Generic[T]):
def transform(self, x: Iterable[T]) -> Iterable[T]:
raise NotImplementedError()
class B(A[str]):
def transform(self, x: Iterable[str]) -> Iterable[str]:
return [x.upper() for x in x]
Now, our uses_a_or_subclass function from up above should be rewritten to either be generic, or to accept specifically classes that subtype A[str]. Either way works, depending on what you're trying to do.

Pharo method with multiple arguments

I am creating a Pharo Class method that takes 3 arguments. I am using the following code and it gives me the error "Variable or expression expected.."
MethodName: arg1:argValue1 arg2:argValue2
^ self var1: argValue1 var2: self var3: argValue2
What would be the correct method declaration syntax? Later on, I intend on calling this method like below :
ClassName var1: argValue1 var2: self var3: argValue2
The bit that you have to understand when it comes to naming methods in Smalltalk is that the method can be split into multiple parts, delimited by colons (:), and that the arguments are inserted after each of those colons. Semantically, that makes a lot of sense, and allows you to use good naming practices so that your code reads almost like an English sentence (which is why the language was named Smalltalk).
So for a method that, in Java or a similar "curly bracket language", might look something like this:
registerUser(String emailAddress, String password, boolean isAdmin) {...}
you would split up the method name in the declaration to fit the arguments, like this:
registerUserWithEmail: anEmailAddress password: aPassword isAdmin: aBoolean
making the method name (often prefixed with # in Smalltalk because it is registered as a "symbol" in a global dictionary):
#registerUserWithEmail:password:isAdmin:
That whole thing is the method name, and when calling it, you'd insert the appropriate arguments after the colons (let's assume this method is defined in the class UserRegistry):
UserRegistry
registerUserWithEmail: 'joe#bloggs.com'
password: 'topSecret'
isAdmin: true
Of course you can leave all that on one line, depending on its length and your readability preferences.
Getting back to your case, you had this:
MethodName: arg1:argValue1 arg2:argValue2
The problem to which your compiler is trying to alert you when it says "Variable or expression expected" is that there's nothing between MethodName: and arg1:. I think you may have assumed that MethodName: wasn't part of the method name but part of the definition.
Some notes:
by convention, method names use lowerCamelCase
#methodName:arg1:arg2: wouldn't make a very good method name in Smalltalk, because the name should describe what it does and, when arguments come into play, what arguments are expected; the same goes for #var1:var2:var3:
if you're going to be calling this method by sending a message to ClassName, then that method needs to be defined on the class side of ClassName, not on the instance side
think about what you're calling/passing in your example - unless you're doing something complicated with a hierarchy of objects, there may not be much point in sending a message to self with one of the arguments being self as well; ask yourself whether you can simplify something there (hard to be more concrete without knowing what you're trying to do)
What you wrote is correct, but MethodName is extra and then your method would look like this:
arg1: argValue1 arg2: argValue2
^ self var1: argValue1 var2: self var3: argValue2
Which is a 2 arg method. You can write 3 arg method in a same way:
arg1: argValue1 arg2: argValue2 arg3: argValue3
^ self var1: argValue1 var2: self var3: argValue2
Then what you are doing is calling another 3 arg class method #var1:var2:var3: with arguments: argValue1, self, argValue2 (I hope this is your intension because this looks weird).

Resources