What's the type of cls introduced by #classmethod - python-typing

I have a simple class C with a #classmethod and a dataclass DC:
#dataclass
class DC:
c_class: ???
class C:
#classmethod
def hello(cls) -> DC:
return DC(cls)
What's the type of cls ? I need to declare it as part of c_class in the #dataclass DC, so I also need to specify the exact type of it.

Thanks to all who commented on the question.
The answer is indeed:
#dataclass
class DC:
c_class: Type['C'] # or Type[C], if C is already defined
I verified, mypy and PyCharm like it and PyCharm even detects the proper class members available to c_class, as I needed. I'm building a strongly-typed software, comments and hints to solve this issue were appreciated.

Related

Why isn't Python NewType compatible with isinstance and type?

This doesn't seem to work:
from typing import NewType
MyStr = NewType("MyStr", str)
x = MyStr("Hello World")
isinstance(x, MyStr)
I don't even get False, but TypeError: isinstance() arg 2 must be a type or tuple of types because MyStr is a function and isinstance wants one or more type.
Even assert type(x) == MyStr or is MyStr fails.
What am I doing wrong?
Cross-reference: inheritance from str or int
Even more detailed in the same question: https://stackoverflow.com/a/2673802/1091677
If you would like to subclass Python's str, you would need to do the following way:
class MyStr(str):
# Class instances construction in Python follows this two-step call:
# First __new__, which allocates the immutable structure,
# Then __init__, to set up the mutable part.
# Since str in python is immutable, it has no __init__ method.
# All data for str must be set at __new__ execution, so instead
# of overriding __init__, we override __new__:
def __new__(cls, *args, **kwargs):
return str.__new__(cls, *args, **kwargs)
Then:
x = MyStr("Hello World")
isinstance(x, MyStr)
returns True as expected
As at python 3.10...
I'd speculate that the answer to
"Why isn't Python NewType compatible with isinstance and type?"
... is "It is a limitation of NewType".
I'd speculate that the answer to
"What am I doing wrong?"
... is "nothing". You are assuming NewType makes a new runtime type, it appears that it doesn't.
And for what it's worth, I wish it did work.
maybe you want a type that is methods like str does but is not a str?
A simple way to get that effect is just:
class MyStr:
value:str
def __init__(self,value:str):
self.value=value
pass
... but that means using all the string methods is "manual", e.g.
x=MyStr('fred')
x.value.startswith('fr')
... you could use #dataclass to add compare etc.
This is not a one-size-fits-all answer, but it might suit your application.
then make that simple
class MyStr:
value:str
def __init__(self,value:str):
self.value=value
...generic like Str in (incomplete) https://github.com/urnest/urnest/blob/master/xju/newtype.py
... and you can write:
class MyStrType:pass; class MyOtherStrType:pass
class MyStr(Str[MyStrType]):
pass
class MyOtherStr(Str[MyOtherStrType]):
pass
x=MyStr('fred')
y=MyOtherStr('fred')
x < y # ! mypy error distinct types MyStr and MyOtherStr
That's what I was after, which might be what you were after? I have to provide Int,Str separately but in my experience distinct int, str, float, bool, bytes types give a lot of readability and error-rejection leverage. I will add Float, Bool, Bytes to xju.newtype soon and give them all the full set of methods.
looks might have been "fixed" in python 3.10:
https://docs.python.org/3/library/typing.html?highlight=typing#newtype
says:
Changed in version 3.10: NewType is now a class rather than a function. There is some additional runtime cost when calling NewType over a regular function. However, this cost will be reduced in 3.11.0.
I don't have 3.10 handy as I write this to try your example.

Graphene mutation with list as input

I have a graphene mutation like this:
class User(ObjectType):
username = String()
class ImportUsers(Mutation):
class Arguments:
users = List(User)
Output = List(User)
#staticmethod
def mutation(root, info, users):
...
But graphene gives me the following error: AssertionError: Mutations.importUsers(users:) argument type must be Input Type but got: [User].
How can I have a mutation in graphene which accepts a list of objects?
I was trying roughly the same thing as you did.
Figured out that custom input types should inherit from graphene.InputObjectType instead of graphene.ObjectType.
class User(graphene.InputObjectType): # <-- Changed to InputObjectType
username = graphene.String()
So, having your User like this should solve the case.
Yeah so, basically, you need to have this:
class User(graphene.ObjectType):
username = graphene.String()
class ImportUsers(Mutation):
class Arguments:
users = graphene.List(User)
Output = graphene.List(User)
#staticmethod
def mutation(root, info, users):
...
Graphene has a List type. Also, I don't know if it's just me or not, but I think you need to have graphene.(type), not just the type. I am working on something very similar right now to this, so hopefully you find or found your solution, and if you do, let me know how it went! Hopefully I helped xD. I am kinda new to all of this so ye

Why can't `Self` be used to refer to an enum's variant in a method body?

This question is now obsolete because this feature has been implemented. Related answer.
The following Rust code fails to compile:
enum Foo {
Bar,
}
impl Foo {
fn f() -> Self {
Self::Bar
}
}
The error message confuses me:
error[E0599]: no associated item named `Bar` found for type `Foo` in the current scope
--> src/main.rs:7:9
|
7 | Self::Bar
| ^^^^^^^^^
The problem can be fixed by using Foo instead of Self, but this strikes me as strange since Self is supposed to refer to the type that is being implemented (ignoring traits), which in this case is Foo.
enum Foo {
Bar,
}
impl Foo {
fn f() -> Self {
Foo::Bar
}
}
Why can't Self be used in this situation? Where exactly can Self be used*? Is there anything else I can use to avoid repeating the type name in the method body?
* I'm ignoring usage in traits, where Self refers to whatever type implements the trait.
An important thing to note is that the error said associated item. enum Foo { Baz } doesn't have associated items. A trait can have an associated item:
trait FooBaz { type Baz }
// ^~~~~~~~ - associated item
To summarize:
Why can't Self be used in this situation?
Because of this issue. RFC 2338 has not been implemented yet.
Self seems to act as a type alias, albeit with some modifications.
Where exactly can Self be used?
Self can only be used in traits and impls. This code:
struct X {
f: i32,
x: &Self,
}
Outputs the following:
error[E0411]: cannot find type `Self` in this scope
--> src/main.rs:3:9
|
3 | x: &Self,
| ^^^^ `Self` is only available in traits and impls
This is possibly a temporary situation and might change in the future!
More precisely, Self should be used only as part of method signature (e.g. fn self_in_self_out(&self) -> Self) or to access an associated type:
enum Foo {
Baz,
}
trait FooBaz {
type Baz;
fn b(&self) -> Self::Baz; // Valid use of `Self` as method argument and method output
}
impl FooBaz for Foo {
type Baz = Foo;
fn b(&self) -> Self::Baz {
let x = Foo::Baz as Self::Baz; // You can use associated type, but it's just a type
x
}
}
I think user4815162342 covered the rest of the answer best.
If the enum name Foo is in reality long and you want to avoid repeating it across the implementation, you have two options:
use LongEnumName as Short at module level. This will allow you to return Short::Bar at the end of f.
use LongEnumName::* at module level, allowing an even shorter Bar.
If you omit pub, the imports will be internal and won't affect the public API of the module.
This is now possible as of version 1.37.
Enum constructors != associated items.
It is a known issue, but it's not expected to be fixed, at least not in the foreseeable future. From what I have gathered it is not trivial to just allow this to work; at this point it is more likely that the related documentation or the error message will be improved.
There is little documentation I could find on the topic of associated items in general; The Rust Book has a chapter on associated types, though. In addition, there are plenty of good answers about Self in this related question.
There is an experimental feature that would make your example work without any other changes. You can try it out in a nightly build of Rust by adding this in your main file:
#![feature(type_alias_enum_variants)]
You can follow the progress of the feature towards stabilisation in its tracking issue.

Pascal passing object of inheritance class to procedure

I have types declared as:
TPlayer = class(TObject)
TBullet = class(TObject)
TEnemy = class(TObject)
and objects:
Player: TPlayer;
PlayerBullets: Array[1..20] of TBullet;
Enemies: Array[1..20] of TEnemy;
EnemyBullets: Array[1..20] of TBullet;
Now I want to create TBullet constructor, which can process informations from both Player and Enemies. In short, I want this constructor to handle both TPlayer and TEnemy objects.
My idea is:
constructor TBullet.Create(const Source: TObject);
Sadly it does not work. How to do this?
EDIT:
My exact problem is: when I pass TPlayer or TEnemy object to this constructor it doesn't see atributes of those objects. For example: TPlayer has attr xPos. If I use Bullet.Create(Player) and in TBullet.Create I use Source.xPos I get an error.
I can think of 3 ways to achieve that.
Have TPlayer and TEnemy both derive from the same base class that have all the information TBullet's constructor need, and have the constructor parameter of that type.
Define an interface contains all the information needed by TBullet and have TPlayer and TEnemy implement that interface
Leave everything "as is" and manage the different class in a "hard coded" manner in TBullet's constructor.
By that I mean:
constructor TBullet.Create(const Source: TObject);
var
vPlayer : TPlayer;
vEnemy : TEnemy;
begin
if Source is TPlayer then
begin
vPlayer := TPlayer(Source);
[Do whatever with vPlayer]
end else if Source is TEnemy then
begin
vEnemy := TEnemy(Source);
[Do Whatever with vEnemy]
end;
end;
Which solution is the best? That could be a debate in itself and largely dependant on your specific situation. Based solely on the name of your class, I'd guess option 1 could be valid. A "TCharacter" class could be created and use as a base calss for both TCharacter and TEnemy. But this is mere speculation at this point.
In windows there is little difference in inheriting from a parent with the common methods (could be abstract in the parent ) or implementing an interface (when again the behavior could be customized ).
If you have an enumeration commonParticipant( cpPlayer, cpEnemy) then Windows allows access to the ultimate parent IUnknown and then down again to a child interface that identifies the methods peculiar to that child, i.e. you can pass an ICommonParticipant including the commonParticipant and then work with either a iPlayer or IEnemy interface

ipython parallel push custom object

I am unable to send object to direct view workers.
Here is what I want to do:
class Test:
def __init__(self):
self.id = 'ddfdf'
from IPython.parallel import Client
rc = Client()
dv = rc[:]
t = Test()
dv['t'] = t
print dv['t']
NameError: name 't' is not defined
This would work if I try to push pandas object or any of the build in objects.
What is the way to do it with custom object?
I tried:
dv['Test'] = Test
dv['t'] = t
print dv['t']
UnpicklingError: NEWOBJ class argument isn't a type object
For interactively defined classes (in __main__), you do need to push the class definition, or use dill. But even this doesn't appear to work for old-style classes, which is a bug in IPython's handling of old-style classes[1]. This code works fine if you use a new-style class:
class Test(object):
...
instead of on old-style class. Note that old-style classes are not available in Python 3.
It's generally a good idea to always use new-style classes anyway.

Resources