Skip to content

Commit afc62bd

Browse files
committed
更新文档 Python中泛型类型的创建和使用方式,简化泛型类名表示法
1 parent e3ad58d commit afc62bd

File tree

4 files changed

+131
-92
lines changed

4 files changed

+131
-92
lines changed

doc/unity/en/tutorial/lang-comparison.md

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ print(outB[0], refC[0]) # 100, 20
114114
|----------|--------------------|---------------------|
115115
| **JavaScript** | `List$1` | `puer.$generic(CS.System.Collections.Generic.List$1, CS.System.Int32)` |
116116
| **Lua** | `List_1` | `puerts.generic(CS.System.Collections.Generic.List_1, CS.System.Int32)` |
117-
| **Python** | `List__T1` (import) or `` List`1 `` (load_type) | `puerts.generic(List, System.Int32)` |
117+
| **Python** | `List` | `List[System.Int32]` |
118118

119-
> The backtick `` ` `` substitute differs across languages: JS uses `$`, Lua uses `_`, Python import uses `__T`.
119+
> In Python, using `import XXX` imports a special generic factory type. When called with type arguments, it creates an instance of a generic type based on the number of mixed-in type arguments.
120120
121121
---
122122

@@ -126,7 +126,7 @@ print(outB[0], refC[0]) # 100, 20
126126
|----------|--------|
127127
| **JavaScript** | Call directly, V8 auto-infers type parameters |
128128
| **Lua** | `puerts.genericMethod(Type, 'MethodName', GenericArgs...)` |
129-
| **Python** | `puerts.genericMethod(Type, 'MethodName', GenericArgs...)` |
129+
| **Python** | `puerts.generic_method(Type, 'MethodName', GenericArgs...)` |
130130

131131
```lua
132132
-- Lua example
@@ -136,7 +136,21 @@ func(obj)
136136

137137
---
138138

139-
## 10. typeof
139+
## 10. Array and Indexer Access (`[]` Operator)
140+
141+
C# `[]` operators (arrays, `List`, `Dictionary`, custom indexers) **cannot** be accessed directly with `[]` in these three languages. You must use `get_Item()` / `set_Item()`.
142+
143+
| Language | Read (C# `arr[0]`) | Write (C# `arr[0] = val`) |
144+
|----------|---------------------|---------------------------|
145+
| **JavaScript** | `arr.get_Item(0)` | `arr.set_Item(0, val)` |
146+
| **Lua** | `arr:get_Item(0)` | `arr:set_Item(0, val)` |
147+
| **Python** | `arr.get_Item(0)` | `arr.set_Item(0, val)` |
148+
149+
> ⚠️ Lua uses colon `:` syntax for instance methods, while JS and Python use dot `.` syntax. This rule applies to all C# types with indexers (arrays, `List`, `Dictionary`, etc.).
150+
151+
---
152+
153+
## 11. typeof
140154

141155
| Language | Syntax |
142156
|----------|--------|
@@ -146,7 +160,7 @@ func(obj)
146160

147161
---
148162

149-
## 11. null Representation
163+
## 12. null Representation
150164

151165
| Language | Script-side null | Notes |
152166
|----------|-----------------|-------|
@@ -156,7 +170,7 @@ func(obj)
156170

157171
---
158172

159-
## 12. Callbacks / Lambda
173+
## 13. Callbacks / Lambda
160174

161175
| Language | Example |
162176
|----------|---------|
@@ -174,7 +188,7 @@ fn("hello");
174188

175189
---
176190

177-
## 13. Throwing Exceptions
191+
## 14. Throwing Exceptions
178192

179193
| Language | Syntax |
180194
|----------|--------|
@@ -190,8 +204,8 @@ fn("hello");
190204

191205
| Feature | JavaScript (`puer.xxx`) | Lua (`require('puerts').xxx`) | Python (`puerts.xxx`) |
192206
|---------|------------------------|------------------------------|----------------------|
193-
| Generic type | `puer.$generic()` | `puerts.generic()` | `puerts.generic()` |
194-
| Generic method | — (auto-inferred) | `puerts.genericMethod()` | `puerts.genericMethod()` |
207+
| Generic type | `puer.$generic()` | `puerts.generic()` | You can import the generic directly using `import` (e.g., `import List`). For details, refer to the explanation of generics above. |
208+
| Generic method | — (auto-inferred) | `puerts.genericMethod()` | `puerts.generic_method()` |
195209
| typeof | `puer.$typeof()` | `puerts.typeof()` | `puerts.typeof()` |
196210
| ref/out create | `puer.$ref()` | `{}` (table) | `[]` (list) |
197211
| ref/out retrieve | `puer.$unref()` | `[1]` | `[0]` |

doc/unity/en/tutorial/python2cs.md

Lines changed: 89 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -50,24 +50,6 @@ Diagnostics.Debug.WriteLine('Test')
5050

5151
PuerTS extends Python's `import` mechanism to directly import C# namespaces and types. You can use standard Python `import` / `from ... import` / `import ... as` syntax.
5252

53-
**Method 2: Using `puerts.load_type()` for dynamic loading**
54-
55-
```csharp
56-
void Start() {
57-
var env = new Puerts.ScriptEnv(new Puerts.BackendPython());
58-
env.Eval(@"
59-
exec('''
60-
# load a type by full name string
61-
TestHelper = puerts.load_type('Puerts.UnitTest.TestHelper')
62-
Vector3 = puerts.load_type('UnityEngine.Vector3')
63-
''')
64-
");
65-
env.Dispose();
66-
}
67-
```
68-
69-
`puerts.load_type()` accepts a full type name string, which is useful when dynamically loading types or when the name contains special characters (such as the `+` sign for nested types).
70-
7153
> ⚠️ **Note**: Accessing a non-existent namespace or type will throw a `ModuleNotFoundError` exception.
7254
7355
------------------
@@ -173,19 +155,19 @@ Unlike JS's `puer.$ref()` / `puer.$unref()` and Lua's table `{}` / `[1]`, Python
173155
----------------------------
174156
### Generics
175157

176-
Use `puerts.generic()` to create generic types in Python:
158+
PuerTS supports Python-style square-bracket syntax for instantiating generic types, similar to the `list[int]` syntax in the Python standard library:
177159

178160
```csharp
179161
void Start() {
180162
var env = new Puerts.ScriptEnv(new Puerts.BackendPython());
181163
env.Eval(@"
182164
exec('''
183-
import System
184-
import System.Collections.Generic.List_1 as List
165+
from System.Collections.Generic import List
166+
from System import Int32
185167
186-
# create generic type: List<int>
187-
ListInt = puerts.generic(List, System.Int32)
188-
ls = ListInt()
168+
# use square bracket syntax to create generic type: List<int>
169+
List_Int32 = List[Int32]
170+
ls = List_Int32()
189171
ls.Add(1)
190172
ls.Add(2)
191173
ls.Add(3)
@@ -197,20 +179,20 @@ print(ls.Count) # 3
197179
}
198180
```
199181

200-
> ⚠️ **Special naming for generic types**: In C#, generic type names use backticks to indicate the number of type parameters (e.g. `` List`1 ``). In Python's `import` syntax, backticks must be replaced with `_` followed by the count:
201-
> - `` List`1 ```List_1`
202-
> - `` Dictionary`2 ```Dictionary_2`
203-
>
204-
> When using `puerts.load_type()`, you can use the original backtick format directly:
205-
> ```python
206-
> List = puerts.load_type('System.Collections.Generic.List`1')
207-
> ```
182+
The following import syntaxes are equivalent:
183+
184+
```python
185+
import System.Collections.Generic.List as List
186+
from System.Collections.Generic import List
187+
```
188+
189+
You can also directly use syntax like `List[System.String]` to create a generic type.
190+
191+
For multiple type arguments, separate them with commas: `Dictionary[String, Int32]`.
208192

209193
----------------------------
210194
### Nested Types
211195

212-
C# nested types can be accessed in two ways:
213-
214196
```csharp
215197
void Start() {
216198
var env = new Puerts.ScriptEnv(new Puerts.BackendPython());
@@ -219,34 +201,63 @@ exec('''
219201
from Puerts.UnitTest import TestNestedTypes
220202
from System import Int32, String
221203
222-
# access nested class as attribute of outer class
204+
# access nested class as an attribute of the outer class
223205
InnerClassA = TestNestedTypes.InnerClassA
224206
x = InnerClassA()
225207
print(x.Foo) # Hello
226208
227209
# access generic nested class
228-
InnerClassB_1 = puerts.generic(TestNestedTypes.InnerClassB_1, Int32)
229-
y = InnerClassB_1()
210+
InnerClassB = TestNestedTypes.InnerClassB[Int32]
211+
y = InnerClassB()
230212
print(y.Bar) # Hello
231213
232-
InnerClassB_2 = puerts.generic(TestNestedTypes.InnerClassB_2, Int32, String)
233-
z = InnerClassB_1()
214+
InnerClassB = TestNestedTypes.InnerClassB[Int32, String]
215+
z = InnerClassB()
234216
print(z.Bar) # Hello
235217
''')
236218
");
237219
env.Dispose();
238220
}
221+
```
222+
223+
----------------------------
224+
### Array and Indexer Access
225+
226+
C# `[]` operators (including array indexing, `List` indexing, `Dictionary` indexing, and any custom indexer) **cannot** be accessed directly with Python `[]` syntax for C# objects. You must use `get_Item()` / `set_Item()`:
239227

240-
// use load_type for nested types (with '+' separator)
241-
env.Eval(@"
228+
```csharp
229+
void Start() {
230+
var env = new Puerts.ScriptEnv(new Puerts.BackendPython());
231+
env.Eval(@"
242232
exec('''
243-
Inner = puerts.load_type('Puerts.UnitTest.CSharpModuleTestPython+Inner')
244-
print(Inner.i) # 3
233+
import System
234+
from System.Collections.Generic import List, Dictionary
235+
236+
# create C# array
237+
arr = System.Array.CreateInstance(puerts.typeof(System.Int32), 3)
238+
arr.set_Item(0, 42) # equivalent to C#: arr[0] = 42
239+
val = arr.get_Item(0) # equivalent to C#: val = arr[0]
240+
print(val) # 42
241+
242+
# also applies to List<T>
243+
ListInt = List[System.Int32]
244+
lst = ListInt()
245+
lst.Add(10)
246+
first = lst.get_Item(0) # equivalent to C#: lst[0]
247+
lst.set_Item(0, 20) # equivalent to C#: lst[0] = 20
248+
249+
# also applies to Dictionary<TKey, TValue>
250+
DictStrInt = Dictionary[System.String, System.Int32]
251+
d = DictStrInt()
252+
d.set_Item('key', 100) # equivalent to C#: dict['key'] = 100
253+
v = d.get_Item('key') # equivalent to C#: v = dict['key']
245254
''')
246255
");
256+
env.Dispose();
257+
}
247258
```
248259

249-
> 💡 When using `puerts.load_type()` to access nested types, use the C# reflection `+` separator format (e.g. `OuterClass+InnerClass`).
260+
> ⚠️ **Important**: Although Python native `[]` is used for Python lists/dicts, index access on C# objects must use `get_Item()` / `set_Item()`. This is consistent with JS and Lua rules.
250261
251262
----------------------------
252263
### typeof
@@ -400,6 +411,40 @@ void Start() {
400411
}
401412
```
402413

414+
----------------------------
415+
### Iterators
416+
417+
Use `puerts.gen_iterator()` to convert C# iterable objects (objects implementing `IEnumerable`) into Python iterators, so you can use Python `for ... in` loops:
418+
419+
```csharp
420+
void Start() {
421+
var env = new Puerts.ScriptEnv(new Puerts.BackendPython());
422+
env.Eval(@"
423+
exec('''
424+
from System.Collections.Generic import List
425+
from System import Int32
426+
427+
List_Int32 = List[Int32]
428+
myList = List_Int32()
429+
myList.Add(1)
430+
myList.Add(2)
431+
myList.Add(3)
432+
433+
# convert C# IEnumerable to Python iterator
434+
iter = puerts.gen_iterator(myList)
435+
result = []
436+
for i in iter:
437+
result.append(i)
438+
439+
print(result) # [1, 2, 3]
440+
''')
441+
");
442+
env.Dispose();
443+
}
444+
```
445+
446+
`puerts.gen_iterator()` internally calls the object's `GetEnumerator()` method and wraps it as an iterator object that supports Python iteration protocol (`__iter__` / `__next__`).
447+
403448
-------------
404449
This section covers calling C# from Python. In the next section, we'll go the other direction: [Invoking Python from C#](./cs2python.md).
405450

doc/unity/zhcn/tutorial/lang-comparison.md

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,13 @@ print(outB[0], refC[0]) # 100, 20
110110

111111
## 8. 泛型类型创建
112112

113-
| 语言 | 泛型类名写法 | 创建 `List<int>` |
114-
|------|------------------------------------------------|-----------------|
115-
| **JavaScript** | `List$1` | `puer.$generic(CS.System.Collections.Generic.List$1, CS.System.Int32)` |
116-
| **Lua** | `List_1` | `puerts.generic(CS.System.Collections.Generic.List_1, CS.System.Int32)` |
117-
| **Python** | `List_1``List`(import 时)或 `` List`1 ``(load_type 时) | `List[System.Int32]` |
113+
| 语言 | 泛型类名写法 | 创建 `List<int>` |
114+
|------|--------------------------------------|-----------------|
115+
| **JavaScript** | `List$1` | `puer.$generic(CS.System.Collections.Generic.List$1, CS.System.Int32)` |
116+
| **Lua** | `List_1` | `puerts.generic(CS.System.Collections.Generic.List_1, CS.System.Int32)` |
117+
| **Python** | `List` | `List[System.Int32]` |
118118

119-
> Python 使用 `import XXX_1```load_type['XXX`1']`` 来获取泛型类型时,会导入类型 ``XXX`1``,而使用 `import XXX` 则会导入一个特殊的泛型工厂类型,调用时传入类型参数即可根据掺入的类型参数数量创建泛型类型实例。
120-
> 两者都可以使用 `List[System.Int32]` 来创建 `List<int>`,但前者需要(也可以用as来调整为`List`)写成 `List_1[System.Int32]`,后者则更简洁。
121-
122-
> 三种语言中反引号 `` ` `` 的替代符不同:JS 用 `$`,Lua 用 `_`,Python import 时用 `_`
119+
> Python 使用 `import XXX` 会导入一个特殊的泛型工厂类型,调用时传入类型参数即可根据掺入的类型参数数量创建泛型类型实例。
123120
124121
---
125122

@@ -207,7 +204,7 @@ fn("hello");
207204

208205
| 功能 | JavaScript (`puer.xxx`) | Lua (`require('puerts').xxx`) | Python (`puerts.xxx`) |
209206
|------|------------------------|------------------------------|----------------------|
210-
| 泛型类型 | `puer.$generic()` | `puerts.generic()` | 使用 import 导入泛型即可 (import List_1/List),细节参考上文对泛型的解释 |
207+
| 泛型类型 | `puer.$generic()` | `puerts.generic()` | 使用 import 导入泛型即可 (import List),细节参考上文对泛型的解释 |
211208
| 泛型方法 | — (自动推断) | `puerts.genericMethod()` | `puerts.genericMethod()` |
212209
| typeof | `puer.$typeof()` | `puerts.typeof()` | `puerts.typeof()` |
213210
| ref/out 创建 | `puer.$ref()` | `{}` (table) | `[]` (list) |

0 commit comments

Comments
 (0)