Tutorial 5: 扩展 IronPython
本tutorial 估计耗时: 25- 60 分钟
本tutorial 的目标是实现一个无缝绑定到IronPython 环境的类. 您可以选择练习1-C# 实现, 练习2-Visual
Basic, 或两者都选择. 两个tracks 会生成相应的功能.
Exercise 1: 使用 C# 扩展
本练习中,您将会使用C#语言创建一个支持遍历的类, 自定义操作符和delegates.然后您将会在IronPython
中使用那个类. 值得注意的是Python并不包含类保护成员, 当引入Python中时,这些成员会提示到类公有成员.
而类私有成员在Python 中是不可见的.
Task 1: 实现简单类 - 构造和ToString函数
-
从“开始”菜单打开"SDK Command Prompt" 或 "Visual Studio 2005 Command Prompt".
-
用记事本程序打开 "csextend.cs" 文件(笔者注:没有则创建). 该文件开始为空
notepad csextend.cs
-
在文件开始处添加“using” 子句:
using System.Collections;
-
定义一个简单类:
private int data;
public Simple( int data) {
this .data = data;
}
public override string ToString() {
return String.Format( " Simple<{0}> " , data);
}
}
-
切换回“SDK Command Prompt window” 并使用csx.bat (C# extension)来构建代码:
csx
-
在tutorial 路径下打开IronPython 控制台.
-
加载您刚才创建的csextend.dll到IronPython. 然后使用内置的dir() 来显示这个简单类:
import clr
clr.AddReferenceToFile("csextend.dll")
clr.AddReferenceToFile("csextend_5.1.1.dll")
import Simple
dir(Simple)
您会看到如下输出:
>>> import clr
>>> clr.AddReferenceToFile("csextend.dll")
>>> import Simple
>>> dir(Simple)
['Equals', 'Finalize', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals',
'ToString', '__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__',
'__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__str__']
-
创建这个简单类的实例:
s = Simple(10)
print s
IronPython 输出:
>>> s = Simple(10)
>>> print s
Simple<10
-
您已探查(explored)了这个简单类中的全部有效功能. 退出IronPython 并返回到C# 代码以例添
加更多功能.
Task 2: 使用对象支持遍历
-
在记事本程序里, 添加更多的功能到这个简单类中.
-
首先使简单类继承自“IEnumerable”并实现GetEnumerator()方法. 使用C#中的声明"yield return":
private int data;
public Simple( int data) {
this .data = data;
}
public override string ToString() {
return String.Format( " Simple<{0}> " , data);
}
public IEnumerator GetEnumerator() {
for ( int i = 0 ; i < data; i ++ ) {
yield return new Simple(i);
}
}
}
-
保存修改内容, 编辑该代码(csx), 运行IronPython 控制台(ip) 并测试代码:
import clr
clr.AddReferenceToFile("csextend.dll")
clr.AddReferenceToFile("csextend_5.1.2.dll")
import Simple
dir(Simple)
['Equals', 'Finalize', 'GetEnumerator', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals', 'ToString', '__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']s = Simple(10)
for i in s: print i
IronPython 控制台显示如下内容:
>>> import clr
>>> clr.AddReferenceToFile("csextend.dll")
>>> import Simple
>>> dir(Simple)
>>> s = Simple(10)
>>> for i in s: print i
Simple<0
Simple<1
Simple<2
Simple<3
Simple<4
Simple<5
Simple<6
Simple<7
Simple<8
Simple<9
Notice that the dir() function now returned the GetEnumerator method.
-
退出IronPython 并返回到 C# 代码以便添加更多功能.
Task 3: 添加自定义操作符(custom operator)
-
添加操作符“+”方法:
using System.Collections;
public class Simple : IEnumerable {
private int data;
public Simple( int data) {
this .data = data;
}
public override string ToString() {
return String.Format( " Simple<{0}> " , data);
}
public IEnumerator GetEnumerator() {
for ( int i = 0 ; i < data; i ++ ) {
yield return new Simple(i);
}
}
public static Simple operator + (Simple a, Simple b) {
return new Simple(a.data + b.data);
}
}
-
返回到命令提示行, 编译代码(csx), 运行IronPython 控制台 (ip) 并测试代码:
import clr
clr.AddReferenceToFile("csextend.dll")
clr.AddReferenceToFile("csextend_5.1.3.dll")
import Simple
dir(Simple)
a = Simple(10)b = Simple(20)
a + b
请注意:调用dir() 后,输出的方法中包括额外的“__add__” 和 “__radd__”的方法, 即Python
对于自定义操作符的解释(notion):
>>> import clr
>>> clr.AddReferenceToFile("csextend.dll")
>>> import Simple
>>> dir(Simple)
>>> a = Simple(10)
>>> b = Simple(20)
>>> a + b
<Simple object at 0x000000000000002B [Simple<30]
-
退出IronPython 并返回到C# 代码以便添加更多功能.
Task 4: 添加 delegate
-
添加delegate 定议到 C# 源文件顶部:
using System.Collections;
public delegate int Transformer( int input);
-
为简单类添加"Transform" 方法,使用delegate 作为参数并调用(invokes)该delegate:
using System.Collections;
public delegate int Transformer( int input);
public class Simple : IEnumerable {
private int data;
public Simple( int data) {
this .data = data;
}
public override string ToString() {
return String.Format( " Simple<{0}> " , data);
}
public IEnumerator GetEnumerator() {
for ( int i = 0 ; i < data; i ++ ) {
yield return new Simple(i);
}
}
public int Transform(Transformer t) {
return t(data);
}
public static Simple operator + (Simple a, Simple b) {
return new Simple(a.data + b.data);
}
}
-
返回到SDK 命令提示行, 编译代码 (csx), 运行IronPython 控制台 (ip) 并测试该code:
import clr
clr.AddReferenceToFile("csextend.dll")
clr.AddReferenceToFile("csextend_5.1.4.dll")
import Simple
a = Simple(10)
def X(i):
return i + 100
a.Transform(X)
函数“X”被作为delegate传递到Simple的Transform方法(The function X is getting passed as
the to the Simple's Transform method). 您会得到如下输出:
>>> import clr
>>> clr.AddReferenceToFile("csextend.dll")
>>> import Simple
>>> a = Simple(10)
>>> def X(i):
... return i + 100
...
>>> a.Transform(X)
110
-
该练习包括C# 扩展例子. 您如果有兴趣, 一个有趣的练习将“调试”例子与“扩展”例子结合起
来.如果您乐于这样做, 尝试调用您刚敲入的脚本. 调试脚本"debugcsx.py" 文件位于Tutorial 路径下,在
“X”函数上设置一个断点 - 您会看到C# 和 Python 的混合调用堆栈(mixed call stack).
Exercise 2: 使用Visual Basic.NET扩展
在这练习中,您会了解到使用Visual Basic .NET 语言创建一个类,该类支持遍历, 自定义操作符和
delegates 以及在IronPython中使用该类. 值得注意的是 Python 并不包括类“保护”成员, 这些成员会
在引入到Python后,转为类“公有”成员. 而私有成员在引入后为不可见.
Task 1: 简单类实现 - 构造和ToString函数
-
从“开始”菜单下打开"SDK Command Prompt" 或 "Visual Studio 2005 Command Prompt".
-
通过记事本打开"vbextend.vb" 文件. 这个文件初始为空
notepad vbextend.vb
-
添加文件顶部添加“Imports”子句:
Imports System.Collections
-
定义一个简单类:
Private data As Integer
Public Sub New ( ByVal data As Integer )
Me .data = data
End Sub
Overrides Function ToString() As String
Return String .Format( " Simple<{0}> " , data)
End Function
End Class
-
切换到“SDK Command Prompt window”并使用 vbx.bat 来构建代码(Visual Basic extension):
vbx
-
在tutorial 路径下启动IronPython 控制台.
-
加载刚创建的dll文件(vbextend.dll) 到IronPython. 然后使用内置的dir()函数控查简单类:
import clr
clr.AddReferenceToFile("vbextend.dll")
clr.AddReferenceToFile("vbextend_5.2.1.dll")
import Simple
dir(Simple)
您会看到如下输出:
>>> import clr
>>> clr.AddReferenceToFile("vbextend.dll")
>>> import Simple
>>> dir(Simple)
['Equals', 'Finalize', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals',
'ToString', '__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__',
'__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__str__']
-
创建简单类实例:
s = Simple(10)
print s
IronPython 会输出:
>>> s = Simple(10)
>>> print s
Simple<10
-
您已查看了简单类中所有的功能. 退出IronPython 并返回到Visual Basic 代码以便添加更多功能.
Task 2: 使用对象支持遍历
-
返回记事本, 为vbextend.vb(简单类) 添加更多功能,
-
首先,将简单类从IEnumerable下继承并实现GetEnumerator() 方法. 与C#不同, Visual Basic 未
提供“yield”关键字来实现“IEnumerable”接口,要求添加一个助手类“SimpleEnum”:
Imports System.Collections
Public Class SimpleEnum
Implements IEnumerator
Private data As Integer
Private curr As Integer
Public Sub New ( ByVal data As Integer )
Me .data = data
Me .curr = - 1
End Sub
Public ReadOnly Property Current() As Object _
Implements IEnumerator.Current
Get
Return New Simple(curr)
End Get
End Property
Public Function MoveNext() As Boolean _
Implements IEnumerator.MoveNext
curr += 1
Return curr < data
End Function
Public Sub Reset () Implements IEnumerator.Reset
curr = - 1
End Sub
End Class
Public Class Simple
Implements IEnumerable
Private data As Integer
Public Sub New ( ByVal data As Integer )
Me .data = data
End Sub
Overrides Function ToString() As String
Return String .Format( " Simple<{0}> " , data)
End Function
Function GetEnumerator() As IEnumerator _
Implements IEnumerable.GetEnumerator
Return New SimpleEnum(data)
End Function
End Class
-
编译代码(vbx), 运行IronPython 控制台 (ip) 并测试该代码:
import clr
clr.AddReferenceToFile("vbextend.dll")
import Simple
dir(Simple)
s = Simple(10)for i in s: print i
在IronPython 控制台中,您会得到如下输出:
>>> import clr
>>> clr.AddReferenceToFile("vbextend.dll")
>>> import Simple
>>> dir(Simple)
>>> s = Simple(10)
>>> for i in s: print i
Simple<0
Simple<1
Simple<2
Simple<3
Simple<4
Simple<5
Simple<6
Simple<7
Simple<8
Simple<9
请注意:现在dir() 函数会返回该GetEnumerator 方法.
-
退出IronPython 并返回到Visual Basic 代码以便添加更多功能.
Task 3: 添加自定义操作符(custom operator)
-
为“Simple”类添加操作符“+”方法:
Implements IEnumerable
Private data As Integer
Public Sub New ( ByVal data As Integer )
Me .data = data
End Sub
Overrides Function ToString() As String
Return String .Format( " Simple<{0}> " , data)
End Function
Function GetEnumerator() As IEnumerator _
Implements IEnumerable.GetEnumerator
Return New SimpleEnum(data)
End Function
Shared Operator + ( ByVal a As Simple, ByVal b As Simple) As Simple
Return New Simple(a.data + b.data)
End Operator
End Class
-
编译代码(vbx), 运行IronPython 控制台 (ip) 并测试该代码:
import clr
clr.AddReferenceToFile("vbextend.dll")
import Simple
dir(Simple)
a = Simple(10)b = Simple(20)
a + b
请注意:您调用dir() 函数可以得到额外的方法“__add__”和“__radd__”, 即Python对于
自定义操作符的解释(notion):
>>> import clr
>>> clr.AddReferenceToFile("vbextend.dll")
>>> import Simple
>>> dir(Simple)
>>> a = Simple(10)
>>> b = Simple(20)
>>> a + b
<Simple object at 0x000000000000002B [Simple<30]
-
退出IronPython 并返回到Visual Basic .NET 代码以便添加更多功能.
Task 4: 添加 delegate
-
在Visual Basic 源文件顶部添加delegate 定义:
Imports System.Collections
Public Delegate Function Transformer( ByVal input As Integer ) As Integer
-
为Simple类添加 "Transform" 方法,以delegate做为参数并调用该delegate:
Implements IEnumerable
Private data As Integer
Public Sub New ( ByVal data As Integer )
Me .data = data
End Sub
Overrides Function ToString() As String
Return String .Format( " Simple<{0}> " , data)
End Function
Function GetEnumerator() As IEnumerator _
Implements IEnumerable.GetEnumerator
Return New SimpleEnum(data)
End Function
Function Transform( ByVal t As Transformer) As Integer
Return t(data)
End Function
Shared Operator + ( ByVal a As Simple, ByVal b As Simple) As Simple
Return New Simple(a.data + b.data)
End Operator
End Class
-
返回到“SDK command prompt”, 编译代码(vbx), 运行IronPython控制台(ip)并测试该代码:
import clr
clr.AddReferenceToFile("vbextend.dll")
import Simple
a = Simple(10)
def X(i):
return i + 100
a.Transform(X)
函数“X”被作为delegate传递到Simple的Transform方法(The function X is getting passed
as the delegate to the Simple's Transform method). 您会得到如下输出:
>>> import clr
>>> clr.AddReferenceToFile("vbextend.dll")
>>> import Simple
>>> a = Simple(10)
>>> def X(i):
... return i + 100
...
>>> a.Transform(X)
110
-
该练习包括Visual Basic 扩展例子. 您如果有兴趣, 一个有趣的练习将“调试”例子与“扩
展”例子结合起来. 如果您乐于这样做, 尝试调用您刚敲入的脚本. 调试脚本"debugvbx.py" 文件位
于Tutorial 路径下,在“X”函数上设置一个断点 - 您会看到C# 和 Python 的混合调用堆栈(mixed
call stack).
Tutorial 总结
csextend.cs 和 vbextend.vb 文件的完整版本位于Tutorial路径下,与这两个文件在一起的还有
csxtest.py 和vbxtest.py 两个文件。而后面的这两个文件就是相应的C# 与 Visual Basic .NET扩展
测试代码.
The code to experiment with debugging of Python and C# or Visual Basic code, use Python scripts debugcsx.py and debugvbx.py respectively.
本tutorial 中您做了如下练习.
本tutorial 中, 您实现了一个简单类,并在IronPython 中使用该类. 您为IronPython 添加了遍
历类的功能, 添加了操作符和对delegate 的支持. 这里有C# 和 Visual Basic 两种实现.
Tutorial 6: 使用Visual Studio 编辑“.py”文件并进行调试
除了.NET的调试支持之外,Visual Studio也支持简单地编辑“.py”文件(no coloring or expression
completion). 本tutorial 告诉您如何用Visual Studio 配置 Python 脚本工作.(This tutorial shows
you how to quickly set up Visual Studio to work on Python scripts in a directory.)
本tutorial 估计耗时: 5 分钟
本tutorial 的目标是配置Visual Studio,一些用于调试的基本工具.
Exercise 1: 配置 Visual Studio 用于IronPython 调试
本练习中,您将会配置Visual Studio 解决方案,编辑路径中的“.py”文件并使用Visual Studio
.NET debugger 进行调试. 我们将Tutorial 路径做为例子, 另外您可在别处保存您的解决方案.
Task 1: 配置 Visual Studio 用于IronPython 调试
-
打开Visual Studio 并关闭其它解决方案和项目.
-
使用“File->Open->Project/Solution ... ”命令并浏览到IronPython 路径下的ipy.exe (比如您
的路径c:"IronPython"ipy.exe). -
我们使用Tutorial 路径做为例子, 然后我们将该路径设置为“工作路径” (working directory)用
于加载“.py” 脚本. 在“Visual Studio's solution explorer ” 右击ipy.exe 项目结点,选择“属性”
(Properties). -
在属性对话框中, 添加两个属性:命令行参数(Command Arguments)和工作路径(Working Directory).
在命令行参数(Command Arguments)中, 敲入"first.py". 在工作路径(Working Directory)中, 敲入Tutorial
路径(c:"IronPython"Tutorial" is where we assume you have it). 单击应用和“OK”确认修改. -
现在使用“File->Save All ... ”命令保存修改. 保存它到Tutorial 路径.
-
为测试我们的配置, 使用“Ctrl+O”打开一个文件. 浏览到Tutorial 路径下的 "first.py" 文件.
放置^ (caret) 到 reads "def add(a, b):" 行上, 接着按 F9 设置一个断点. -
按下 F5 运行脚本, 接着点击该断点. 如您按下 F10, 您会步进(step through)这个文件, 所执行
的都是加载定义和设置变量直到结束. -
为了了解更多的步骤 (stepping), 我们对这个文件添加一行并设置另一个断点. 在文件底部添加
一行并调用factorial 函数("factorial(5)"). 在行reads "if n < 1: return 1" 添加断点. 现在按下F5
运行脚本. 反复按下F10 观察“locals window” 参数 "n" 减少到 0 。then goes back up to 5 as the
recursion unwinds. 您也可以将鼠标放在 "n" 上面, 每次运行到断点处暂停时,得到该变量的数据提示.
为了运行其它脚本, 只要修改“ipy.exe”项目的命令参数,以及其它的script. 您可能也看到“工具->
选项”对话框,改变“环境->文档”上的属性来显示打开的脚本文件. 如选择"Show Miscellaneous Files
in the Solution Explorer", 然后您会得到正在编辑的“.py”文件列表. 以后每次您打开这个解决方案时,
您会看到解决方案下所有开发的“.py”文件.
Tutorial 总结:
本tutorial 中,您做了如下练习.
本tutorial 中,您配置Visual Studio 运行 Python scripts 脚本并调试它们.
好了,到这里终于翻译完了,也快“吐血”了。
感兴趣的朋友可以通过EMAIL或在回复中与我联系。
作者:代震军 (daizhj)
博客:http://daizhj.cnblogs.com