使用Python代替Objective-C的缺点是什么?

13

我了解一些 Python,对这种语言的易用性印象非常深刻。从我所见过的 Objective-C 来看,它看起来不太美观,但似乎是 Mac OS X 开发中的通用语言(这意味着它有更好的文档)。

我正在考虑开始进行 Mac 开发 - 使用 PyObjC+Python 会让我成为二等公民吗?

8个回答

37

是的。

首先,正如您所指出的,所有文档都是针对Objective-C编写的,这是一种非常不同的语言。

一个区别是方法名称。在Objective-C中,当您向对象发送消息(Python会说“调用对象的方法”)时,方法名称(选择器)和参数会混合在一起:

NSURL *URL = /*…*/;
NSError *error = nil;

QTMovie *movie = [QTMovie movieWithURL:URL
    error:&error];

这在Python中是不可能的。Python的关键字参数不算作方法名称的一部分,因此如果你这样做:

movie = QTMovie.movieWithURL(URL, error = ???)

如果你使用QTMovie类中没有名为movieWithURL的方法,你将会得到一个异常;Objective-C示例中的消息使用了选择器movieWithURL:error:movieWithURL:movieWithURL是另外两个选择器。

他们无法改变这一点,因为Python的关键字参数没有顺序。假设你有一个假想的三个参数的方法:

foo = Foo.foo(fred, bar=bar, baz=baz)

现在,这会调用foo:bar:baz:,对吧?

不要那么快。Foo也可能有一个名为foo:baz:bar:的方法。由于Python的关键字参数没有顺序,你实际上可能会调用那个方法。同样地,如果你尝试调用foo:baz:bar:,你实际上可能最终调用foo:bar:baz:。事实上,这种情况不太可能发生,但如果它真的发生了,你将无法可靠地调用任何一个方法。

因此,在PyObjC中,你需要这样调用该方法:

movie = QTMovie.movieWithURL_error_(URL, ???)

你可能对 "???" 感到困惑。C语言不允许多个返回值,因此在Objective-C中,"error:"参数需要指向指针变量的指针,并且该方法将在该变量中存储一个对象(这称为按引用返回)。Python没有指针,因此桥接程序处理此类参数的方式是传递None,然后该方法将(似乎)返回一个元组。因此,正确的示例是:

movie, error = QTMovie.movieWithURL_error_(URL, None)

你可以看到,即使是一个简单的例子,它跟Objective-C文档中所展示的有所偏差。

还有其他问题,比如GIL。Cocoa应用程序将变得更加并发,而且你会想要参与其中,特别是有像NSOperation这样诱人的类存在。而GIL在多核机器上是一个严重的负担。我自己是Python开发者(不写Cocoa代码时),所以我说这个问题是冷酷的事实,无可否认。

因此,如果我要为我的应用程序切换使用别的语言,我会选择MacRuby。与PyObjC和RubyCocoa不同,对Cocoa对象的消息不需要跨语言桥梁;它是一种从底层开始的Cocoa的Ruby实现,具有用于更好地支持在其中编写Cocoa代码的语言扩展。

但那太遥远了。你只是初学者。先从Objective-C开始吧。最好保持相同语言,避免在使用的语言和文档写作所用的语言之间出现任何阻力不匹配。

此外,你会发现某些错误(例如发送给已死亡对象的消息)在没有了解Objective-C工作原理的情况下更难诊断。无论你在哪种语言中编写代码,作为新的Cocoa程序员,你都会写出这些错误。

因此,请先学习C语言,然后再学习Objective-C语言。对C和Objective-C的实用知识不应该超过几周时间,并且最终你将为其他任何事情做好更充分的准备。

我不会详细介绍我是如何学习C语言的;可以说,我不建议这种方法。我听说这本书很好,但我没有拥有或阅读过它。我有这本书,可以证实它很好,但它也不是面向Mac的;跳过关于如何编译代码的章节,改用Xcode。
至于Objective-C:Hillegass的书最受欢迎,但我没有使用过它。(我浏览过它,看起来很不错。)我阅读了苹果公司关于该语言的文档,然后立即开始编写小型Cocoa应用程序。我阅读了一些指南,结果参差不齐。有一个货币转换器教程,但它对我没有帮助,并且不能完全反映现代Cocoa应用程序(现代应用程序仍然使用outlets和actions,但还使用Bindings,而现实中的货币转换器几乎完全是一对Bindings)。

1
对于这个详尽的回答,给予+1和尊重。 - tzot
6
MacRuby 明显是桥接语言中最“本地化”的,但仍然远非本地化。Xcode 不支持它,你无法直接查阅文档,必须先将其翻译成 Objective-C,并且询问基于 MacRuby 的 Cocoa 问题将极大地减少可能能够回答的人数。此外,使用 MacRuby 还需要学习 Objective-C 才能使用 Cocoa APIs,这会增加不必要的复杂性。 - bbum
1
GIL正在被修复的过程中。我观看了那个视频,并想:“我知道如何解决这个问题!至少是朝着解决方案迈出了一大步。”但在获取Python Subversion仓库后,我发现它在大约3个月前已经合并到Python 3K中了。 叹气 - Omnifarious
我一直在苦苦寻找一些适合初学者学习Mac开发的好资源,这里有没有人知道一些好的来源? - Samhan Salahuddin
@Samhan:在这种情况下,“任何人”不会很好地发挥作用:您正在评论一个旧答案,因此不会有太多人遇到这个问题,除非他们有相同的问题;我只看到了您的评论,因为您评论的是我的答案。无论如何,回答您的问题,我在那个非常主题上有一个答案:http://stackoverflow.com/a/6488745/30461 - Peter Hosey
主要问题似乎是PyObjC总是落后于时代,现在我想使用AVFoundation但它还没有准备好,因为苹果公司并没有致力于它,只有一个热心的开发者(无论多么出色)。 - dashesy

18

这段话已经说得很清楚了:

作为 PyObjC 近 15 年的维护者,我直截了当地说:使用 Objective-C。无论如何,你都需要了解 Objective-C 才能真正理解 Cocoa,并且 PyObjC 只会增加一层由 99% 的 Cocoa 程序员难以理解的错误和问题。

这是对此问题答案的评论。这个问题也很有趣。


1
说实话,使用桥接的唯一好理由是如果您真正需要执行某些操作,而没有动态语言功能将使您无法完成。脚本系统和需要遵循Postel法则的东西通常是很好的例子。但通常情况下,是的,您需要Objective-C,尽管与之相比有些痛苦。 - Bob Aman

3

如果你要为Mac编写应用程序,不要试图避免学习Objective-C。PyObjC和其他语言绑定的目的是让你在应用程序中重复使用现有库,而不是让你避免学习本地工具。


2
“二等公民”这个说法有些过于强烈了。实际上,Objective-C的API也可以从Python中调用,但这主要是为了制作Cocoa应用程序。但是,它们仅限于OS X操作系统。个人而言,我对于不能跨平台的应用程序没有兴趣,但这只是我的看法。这也意味着我实际上没有做过这件事情,所以我不知道它有多难。不久前,《Python Magazine》上刊登了一篇文章,它看起来并不太可怕。
Python的一个主要缺点是执行时间,这主要是由于它是一种动态语言造成的。这可以通过Cython和C扩展等方法来解决,但这将使得Python + Objective-C API + Cython的混合使用会变得比较困难。
因此,它非常依赖于你要开发的应用程序类型。如果你要开发一些独特的仅适用于OS X的应用程序,那么Objective-C可能更适合;而如果你需要开发跨平台服务器,那么Python则非常适用!如果是其他类型的应用,则需要根据具体情况而定。

0

这是我一直在思考的问题,虽然我希望有更多经验的人能够提供意见,但根据我的了解,Python本身不会对你造成严重限制。与Java和GCC一起,Python是编写本地跨平台应用程序的绝佳方式。一旦你掌握了它,你应该能够将Objective C的示例代码映射到你的Python代码中。

由于你可以访问所有库和事件,你可以在Python中做任何你在Objective C中能做的事情。当然,你使用的OS X专用调用和函数越多,将其移植到另一个平台就越困难,但这并不是重点。通常,图形编程和设备驱动程序是某种限制因素,但在这两种情况下,我发现有很好的支持和社区库(搜索Python和Quartz、Lightblue、libhid、PyUSB等一些示例)。

对我来说,决定性的因素是:需要什么级别的工具和IDE支持。苹果提供了一些构建新软件的优秀软件,但是像Pydev这样的工具也是编写Python代码的好地方!http://pydev.org/

所以试一试吧,我相信你不会后悔的,而且还有一个支持性强的社区可以寻求帮助和灵感。


0

你需要学习Objective-C:所有的教程、文档、示例代码等都是用这种语言编写的。此外,更多的人可以帮助你。

所以先学习ObjC。如果在你的第二个或第三个项目中,或者一年后,你开始一个需要Python模块的项目(比如Twisted或SQLAlchemy。但是像应用程序基础这样严重的需求,额外的提升会让一切都值得),那么你可以编写一个PyObjC应用程序,并利用你在Cocoa方面的背景获得很多语言的速度优势。


0

作为额外的选择,考虑使用 wxPython ,无论在 Mac 还是在 Linux 和 Windows 上都能生成一些非常好的应用程序。大部分情况下,您可以获得本地外观,但几乎不需要关注特定于平台的问题。

换句话说,PyObjC + Python 不是使用 Python 进行 Mac 开发的唯一方法。


4
如果您想要一个看起来和感觉像 Mac 应用程序的应用,PyObjC + Python 使用 Python 进行 Mac 开发的唯一方法。 wxPython 和 Tk 基础的应用程序则显得格格不入。 - bbum
@bbum,这是一个主观问题,或者说,你所见到的特定例子可能做得不好。无论如何,发表绝对主义观点并不是帮助OP的好方法...(请注意,在您不知道的情况下,wxPython(我相信最新的Tk工具包也是如此)大部分使用本地控件。如何才能导致既不外观也不感觉本地化的问题,您需要解释一下。) - Peter Hansen
2
看起来像本地应用,但感觉并不像。这是因为wx和Tk与Cocoa有不同的交互模型,存在微妙的差异。这不是主观的,而是从20年来观察使用非本地API构建的Mac应用程序在评论中受到抨击得出的结论。工具正在改进,但仍存在阻抗不匹配。 - bbum
@bbum,好的,我误解了你评论中“外观和感觉”部分的含义,认为两者都有问题。我可以接受wxPython目前不像Cocoa应用程序那样感觉...显然它在当前版本中仍基于Carbon。也许随着即将推出的基于Cocoa的版本(据我今天刚听说)的发布,情况会有所改变。 - Peter Hansen

0

不,你不需要了解Objective C,也不需要使用PyObjC,你也不会成为二等公民。

除非你想要做一些极其特定于MAC平台的事情,否则编写Objective C或使用PyObjC是一个非常糟糕的想法。

原因很明显,一旦你选择了objc路线,你就告别了其他平台。就这么简单。

苹果不希望你为其他平台编写代码,就像微软不希望你为其他平台编写代码一样。这就是为什么越来越多的开发人员转向开源语言,如Python、Java、Ruby等。因为你不关心苹果和微软,你只关心最有用和最容易开发的应用程序。而且,将你的应用程序仅限于MAC将使它变得不那么有用,显然使用Objective C进行开发更加困难。

Python拥有足够的库来满足您的需求,数百个库,可立即在mac平台上使用。例如,我使用pygame开发新应用程序,它不是游戏,如果我使用ObjC或PyObj完成同样的事情,我将不得不为Windows和Linux重新编写代码。而使用pygame,即使我的主要平台是macOS,我的代码在Windows和Linux中也完全相同。

这就是大多数Python库的吸引之处,它们是跨平台的。WxPython就是一个例子,有人提到它“并不完全看起来像原生界面”,难道这会阻止你将应用程序发布给Windows和Linux吗?为什么要限制自己只在MAC平台上开发?你觉得普通用户会关心应用程序的原生外观吗?即使macOS应用程序也没有原生外观,其中许多应用程序都带有自己的“眼睛糖果”图形界面。并不是说你不能使WxPython看起来100%原生,编码方式始终很重要。

当你打算开发iPhone OS时,Objective-C是有意义的选择,因为苹果认为排除Python(不仅仅是Python)是一个好主意,尽管他们被迫包括JavaScript(否则在iPhone上上网将成为噩梦)。Pyjamas也可以使Python在iPhone OS上可用(无需任何黑客或越狱手机),但具有明显的限制,因为它将Python代码转换为JavaScript,但直到苹果决定从iPhone OS中排除Python是一个真正糟糕的主意,它仍然是一个有效的解决方案。

链接文本

学习Objective-C并没有什么害处。你始终可以通过pyobjc使用原生库。

但是,说实话,如果我的应用程序在使用Python库时遇到死胡同(这是非常不可能的情况),我宁愿使用Cython包装现有的跨平台C/C++库,而不是采用Objective C PyObjc方法破坏我的应用程序的跨平台能力。我最不想使用的就是任何特定于平台的东西。

现在,如果你完全不关心其他平台,那么我想Objective C可能是一个有效的选择。它看起来确实很丑陋,但我听说随着使用次数的增加,它会变得越来越好,并且有很多人喜欢它胜过C/C++。


有人想开始进行“Mac开发”,你是否会劝他们不要涉足任何特定平台?他们来问关于平台开发的问题。这并没有帮助,也不是主题。 - ipmcc
我认为你把"Mac Development"和"Mac Only Development"混淆了。我认为我的回答清楚地阐述了这一点,并且确实符合主题。如果提问者询问的是"仅限于在Mac系统上开发",那么我的回答会不同,但他并没有这样问。 - Kilon
Occam's Razor:如果 OP 想表达的是多平台开发,他们本应该这样说。但他们没有这么说;他们说的是“Mac 开发”。帖子中没有任何东西 - 标题、正文、标签等 - 表明多平台开发。相反,它被标记为 Cocoa,这明确是面向苹果的。 - ipmcc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接