Python入門教程,Java開發者必須瞭解這些!

本文轉自阿里雲前端

摘要:編者按:在Java文章頻道里,咱們大部分人應該對該語言都很是的瞭解,並且在該生態圈內至少已經呆了好幾年了。這讓咱們有常規和專業的知識,可是也同時也讓咱們一些井蛙之見。 在Outside-In Java系列文章中,一些非Java開發人員會給咱們講講他們對於咱們這個生態圈的見解。java


v2-a51000be38ad0255d6b10ab0417bc1f2_b.jp




從哲學的角度來說,Python幾乎是與Java截然相反。它拋棄了靜態類型和剛性結構,而是使用了一個鬆散的沙盒,在這裏面你能夠自由的作任何你想作的事情。也許Python是關於你可以作什麼,而Java則是關於你能夠作什麼。python

然而,兩種語言都從C語言裏吸收了大量的靈感。他們都是命令式語言,擁有塊、循環、方法、賦值以及中綴算術(infix math)。二者都大量使用了類、對象、繼承以及多態性。二者的功能異常都至關優秀。 二者都能自動管理內存。它們都是編譯成能夠運行在某種虛擬機上的字節碼,儘管Python是透明的進行編譯。 Python甚至從Java汲取了一些養分:好比基本庫的 logging 和 unittest 模塊分別是受到了log4j 和JUnit的啓發。程序員

鑑於以上的技術重疊,我認爲Java開發人員在使用Python時理應感到賓至如歸。 因此我來給你一些簡單的Python介紹。 我會能夠告訴你什麼使得Python與Java不一樣,以及爲何我以爲這些差別有吸引力。 至少,您可能會發現一些有趣的想法使您回到Java生態系統。數據庫

(若是你想要一個Python教程,Python文檔是一個很好的選擇,並且這是從Python 3的角度編寫的,Python 2的使用仍是很常見的,它與Python 3有一些語法上的差別。編程

對於正在學習java但不知道學習方法,不知道該如何找到工做的朋友,我仍是要推薦下我本身建的前端學習羣:240448376,首先你要是學前端的,其次無論你是小白仍是大牛,小編都挺歡迎,羣裏天天都會分享前端相關乾貨,包括我本身(一名工做六年的前端老司機)最近熬夜花了一星期整理出的一份適合2017年自學的最新java前端資料,都送給你們,歡迎初學和進階中的小夥伴。緩存

語法網絡

咱們先把語法弄明白。下面是 hello world入門程序:session

print("Hello, world!")數據結構

嗯, 並非頗有啓發性。 好吧,再來看一個函數,看看如何在一個文件中找到最多見的10個單詞。在這裏我取巧使用了標準庫的 Counter 類型,可是它就是這麼的好用。

fromcollections import Counter

def count_words(path):

words = Counter()

withopen(path)asf:

forlineinf:

forwordinline.strip().split():

words[word] += 1

forword,countinwords.most_common(10):

print(f"{word} x{count}")

Python由空格分隔。人們常常對此有強烈的意見。當我第一次看到它的時候,我 甚至認爲這是異端邪說。如今,十多年過去了,這種寫法彷佛天然到我很難再回到大括號式的寫法。若是你所以逃避,我甚至懷疑我能夠說服你,不過我勸你至少暫時忽略一下它;實際上它並無形成任何嚴重的問題,反而消除了一大堆的干擾。此外,Python開發人員歷來沒必要爭論{應該放在哪裏。

除了審美上的差別以外,其餘方面應該看起來很熟悉。咱們有一些數字,一些賦值和一些方法調用。import 語句的工做方式有些不一樣,但它具備相同的「使這些內容可用」的通常含義。 Python的for循環與Java的for-each循環很是類似,只是少了點標點符號。函數自己使用def而不是類型進行分隔,但它正是按照你指望的方式工做:您可使用參數調用它,而後返回一個值(儘管某些函數不返回值)。

只有兩件事情是很不尋常的。 一個是 with 塊,很是相似於Java 7的「try-with-resources」 – 它保證文件在塊的結尾處關閉,即便會拋出一個異常。 另外一個是f「…」語法,這是一個至關新的功能,容許將表達式直接插入到字符串中。

就是這樣! 你已經讀了一些Python的內容。 至少,它不是來自一個徹底不一樣的星球的語言。

動態類型

看這個例子可能很明顯,可是Python代碼裏沒有太多的類型聲明。 變量聲明上沒有,參數或返回類型上沒有,對象上也沒有。 任何值在任什麼時候候均可以是任何類型的。 我尚未顯示一個類定義,因此這裏只是一個簡單的定義。

class Point:

def __init__(self, x, y):

self.x = x

self.y = y

def magnitude(self):

return(self.x ** 2 + self.y ** 2) ** 0.5

point = Point(3, 4)

print(point.x)  # 3

print(point.magnitude())  # 5.0

儘管x和y有並無定義爲屬性,它們的存在是由於構造器中建立了它們。沒有誰強制我必須傳個整型參數,我也能夠傳小數和分數。

若是你之前只用過靜態語言,這可能看起來一片混亂。類型是溫暖的懶惰的以及使人滿意的。他們保證···(好吧,或許不會)代碼實際能工做(雖然有人不一樣意)。可是當你都不知道什麼是正確類型的時候,你又怎麼能依靠代碼呢?

可是等等 – Java也沒有這樣的保證! 畢竟任何對象可能都是null,對吧? 實際上幾乎歷來沒有一個正確類型的對象。

您可能會將動態類型視爲對null問題的完全放棄。 若是咱們必須處理它,咱們不妨擁抱它,並讓它爲咱們工做 – 經過將一切 延遲到運行時。 類型錯誤變成正常的邏輯錯誤,您能夠以相同的方式處理它們。

(對於相反的方法,請參閱 Rust,它沒有空值 – 或者異常,我仍是寧願寫Python,可是我很欣賞Rust的類型系統並不老是對我說謊。)

在個人magnitude方法中,self.x是int或float或任何其餘類型,這都不重要。 它只須要支持**運算符並返回支持+運算符的內容。 (Python支持操做符重載,因此這多是任何內容。)一樣適用於普通方法調用:任何類型均可以接受,只要它實際上能夠工做。

這意味着Python不須要泛型; 一切都是按照泛型工做的。 不須要接口; 一切都已是多態的。 沒有向下轉型(downcasts),沒有向上轉型(upcasts),在類型系統中沒有逃生艙口(escape hatches)。 當它們能夠和任意Iterable工做良好時,運行時API不須要List。

許多常見的模式變得更加容易。 您能夠建立包裝器對象和代理,而無需更改消費代碼。 您可使用組合而不是繼承來擴展第三方類型,而不須要爲保留多態作任何特殊的操做。 靈活的API不須要將每一個類做爲接口複製; 一切都已經做爲一個隱式接口了。

動態類型哲學

使用靜態類型,不管誰編寫 某些代碼來選擇這些類型,編譯器都會檢查它們是否正常工做。 使用動態類型,不管誰使用 某些代碼來選擇這些類型,運行時都會嘗試一下。 這就是對立的哲學在起做用:類型系統着重於你能夠 作什麼,而不是你可能 作什麼。

這樣使用動態類型有時被稱爲 「鴨子類型」(duck typing),這是基於這種思想: 「若是它走起來像鴨子,並且叫起來也像鴨子,那麼它就是一個鴨子。」 換言之,就是說,若是你想要的是能像鴨子同樣呱呱叫的東西的話,你不用強制你的代碼必須接收一個鴨子對象,相反的你能夠接收任何給你的東西,而且讓它可以呱呱叫便可。若是它能夠達成你的目標的話,那麼它就跟鴨子同樣好用。(不然若是它沒法如你所願,會拋出AttributeError的錯誤,可是這也沒什麼大不了的。)

同時也要注意Python是強類型的。這個詞有點模糊,它一般意味着變量的值在運行時會一直保持其類型不變。一個典型的例子是,Python不會讓你把一個字符串賦值給一個數字類型的變量,而像弱類型語言,如JavaScript 則能夠將一種類型靜默的轉換成另外一種,這裏使用了優先級的規則,跟你的預期會有所不一樣。

與大多數動態語言不一樣的是,Python 在運行以前就能夠捕獲錯誤信息。例如讀取一個不存在的變量會產生一個異常,包括從一個字典對象(如 Map)中讀取一個不存在的鍵時也會報錯。在 JavaScript 、Lua 和相似語言中,上面兩種狀況是返回 null 值。(Java 也是返回 null 值)。若是想在值不存在時返回默認值,字典類提供了更加明確的方法調用。

這裏絕對是一個權衡的結果,是否值得取決於不一樣的項目和人。對我來講,至少很是適合用來設計一個更加可靠的系統,覺得我能夠看到它實際執行的狀況。可是靜態類型的語言都期待有一個預先的設計。靜態類型很難嘗試各類不一樣的想法,更難發揮。

你確實擁有了更少的靜態檢查保證,但根據個人經驗,大多數的類型錯誤能夠正確被捕獲……由於我寫完代碼的第一件事就是嘗試去運行它!其它任何錯誤應該能夠被你的測試所捕獲—測試應該在全部語言中都有,而且python語言寫測試相對來講更容易。

一個混合的範例

Python 和 Java 都是命令式和對象導向的:它們的工做方式是執行指令,它們把每件事物塑造爲對象。

在最近的發行版本中,Java增長了一些函數式語言特徵,我認爲這是一件好事。Python也有函數式語言特徵,可是實現的方式不太同樣。它提供了一些內置的函數如map和reduce,可是它並非基於串聯許多小函數的思想來設計的。

相反,Python混合了其它東西。我不知道Python採用的方法的通用名稱。我認爲它把「函數鏈」的思想分爲兩個:做用於序列上和使函數自身更加有用。

序列

序列和迭代在Python有重要的地位。序列是最基礎的數據結構,做爲於之上的工具很是有價值。我認爲Python對於函數式編程的實現以下:Python首先使得使用命令式代碼來操做序列很是容易,而不是使得結合許多小函數而後應用於序列很是容易。

回到本文開始的地方,我曾寫下這一行代碼:

forword,countinwords.most_common(10):

for循環對咱們來講很熟悉,可是這行代碼一次迭代了兩個變量。 實際發生的是,列表most_common中的每一個元素返回一個元組,它們是一組按順序區分的值。 真正發生的是元組能夠經過將它們分配給元組變量名來解包。 元組一般用於在Python中返回多個值,但它們偶爾也可用於特殊結構。 在Java中,您須要一個完整的類和幾行分配值的代碼。

任何能夠迭代的東西一樣能夠解包。 解包支持任意嵌套,因此a,(b,c)= …按照它看起來的樣子解包。 對於未知長度的序列,一個*leftovers元素能夠出如今任何地方,而且將根據須要獲取儘量多的元素。 也許你真的會喜歡LISP?

values= [5, 7, 9]

head, *tail =values

print(head)  # 5

print(tail)  # (7, 9)

Python還具備經過簡單表達式建立列表的語法 – 所謂的「列表解析」 – 這比函數方法如map更爲常見。 存在相似的語法用於建立分組和集合。 整個循環能夠減小到一個單一的表達式,只突出你真正感興趣的部分。

values= [3, 4, 5]

values2 = [val * 2forvalinvaluesif val != 4]

print(values2) # [6, 10]

標準庫還在itertools模塊中包含了許多有趣的迭代,組合器和用法。

最後,Python具備用於生成命令行代碼的延遲序列的生成器。 包含yield關鍵字的函數在被調用時不當即執行; 而是返回一個生成器對象。 當生成器迭代結束時,該函數運行直到它遇到一個yield,此時它暫停; 生成的值將成爲下一個迭代值。

def odd_numbers():

n = 1

whileTrue:

yield n

n += 2

forxinodd_numbers():

print(x)

if x > 4:

break

# 1

# 3

# 5

由於生成器延遲運行,它們能夠產生無限序列或在中途中斷。 他們能夠產生大量的大型對象,不會由於讓它們所有存活而消耗一大堆內存。 它們也能夠做爲「鏈式」函數編程風格的通常替代。 您能夠編寫熟悉的命令行代碼,而不是組合map和filter。

# Thisisthe pathlib.Path APIfromthe standard library

def iter_child_filenames(dirpath):

forchildindirpath.iterdir():

if child.is_file():

yield child.name

要在Java中表示徹底任意的惰性迭代器,您須要編寫一個手動跟蹤其狀態的Iterator。除了最簡單的狀況以外,這一切都會變得至關棘手。 Python也有一個迭代接口,因此您仍然可使用這種方法,可是生成器很是容易使用,以致於大多數自定義迭代都是用它們編寫的。

並且由於生成器能夠本身暫停,因此它們在其餘一些上下文中是有用的。 經過手動調用生成器(而不是僅用一個for循環來一次性所有迭代),就能夠在一段時間內運行一個功能,讓它在某一點中止,並在恢復該函數以前運行其餘代碼。 Python充分利用這一點來添加對異步I/O(不使用線程的非阻塞網絡)的支持,儘管如今它具備專用的async 和await 語法。

函數

乍一看,Python的函數看上去很是面熟。你可使用參數來調用它們。傳遞風格與Java徹底相同—Python既沒有引用也沒有隱式複製。 Python甚至有「docstrings」,相似於Javadoc註釋,但它是內置的語法而且在運行時可見。

def foo(a, b, c):

"""Print out the arguments. Not a very useful function, really."""

print("I got", a, b, c)

foo(1, 2, 3) # I got 1 2 3

Java具備args …語法的可變函數; Python使用* args能夠實現相似的功能。 (用於解包的*leftovers語法靈感來源於函數語法。)可是,Python還有一些技巧。任何參數均可以有一個默認值,使其成爲可選項。任何參數也能夠經過名稱 給出 – 我以前使用Point(x = 3,y = 4)演示了這點。在調用 任何函數時,可使用* args語法,它將傳遞一個序列,就像它是單獨的參數同樣,而且有一個等價的** kwargs將命名參數做爲一個dict接受或傳遞。一個參數能夠做爲「僅關鍵字(keyword-only)」,因此它必須 經過名稱傳遞,這對於可選的布爾值是很是好的。

Python固然沒有 函數重載,可是你使用它實現的功能大部分均可以被鴨子類型(duck typing)和可選參數替換。

這是現階段Python最強大的功能之一。 與動態類型同樣,您能夠經過包裝器或代理透明地替換對象,* args和** kwargs容許任何函數 被透明地包裝。

def log_calls(old_function):

def new_function(*args, **kwargs):

print("i'm being called!", args, kwargs)

returnold_function(*args, **kwargs)

returnnew_function

@log_calls

def foo(a, b, c=3):

print(f"a = {a}, b = {b}, c = {c}")

foo(1, b=2)

# i'm being called! (1,) {'b': 2}

# a = 1, b = 2, c = 3

這有點難以理解,對不起。 不用擔憂它到底是如何工做的; 要點是,foo被一個new_function替換,它將全部的參數轉發到foo。 foo和調用者都不須要知道哪些事情有哪些不一樣。

我不能低估它有多麼強大。 它可用於記錄,調試,管理資源,緩存,訪問控制,驗證等。 它與其餘元編程功能工做良好,一樣地,它可讓您分解結構,而不只僅是代碼。



v2-9ce28c0b04fce1b18a04985ff6cfe311_b.jp



對象和動態運行時

動態運行時是一種在背後驅動語言核心部分的東西 — 它能夠在運行時被執行。像 C 或者 C++ 這類的語言毫不會具備動態運行時;它們源碼的結構被「烘焙」成編譯輸出,而且後續沒有明顯的方法來改變它的行爲。從另外一方面,Java的確具備動態運行時!它甚至帶有一整個專門用於反射的包。

Python 固然也有反射。不少簡單的函數經過反射被構建,用來聯機檢查或修改對象的屬性,這對調試以及偶爾的欺騙很是有用。

但 Python 對此更深刻一點。 由於一切都在運行時完成,Python 暴露了不少擴展點來自定義它的語義。 你不能改變語法,代碼依然看起來像 Python,但你能夠分解結構 — 這在一種更死板的語言是很是難以作到的。

舉個極端的例子,看下 pytest, 它聰明的處理了 Python 的 assert 聲明。 一般, assert x == 1 爲 false 時只會簡單的拋出一個 AssertionError 異常,致使你不知道錯誤是什麼或者哪裏出錯了。這就是爲何 Python 內置的單元測試模塊 — 像 JUnit 和不少其餘的測試工具 — 提供不少專門的工具函數,好比 assertEquals。不幸的是,這些工具函數使得測試初看到時,更加複雜更難以讀懂。但在 pytest 中, assert x == 1 是好用的。若是失敗,pytest 將告訴你 x 是… 或者兩個列表哪裏有分歧,或者兩個集合哪些元素不一樣, 或者其餘的。全部的這些都是基於比較完成和運算對象的類型自動發生的。

pytest是如何工做的呢? 你確實不想知道。你不須要知道如何用pytest寫測試 — 這令人很開心。

這就是動態運行時的真正優點所在。 就本身而言,可能沒有使用這些功能。可是你能從這些庫中收穫巨大的好處,你使用這些庫並不須要關心它們如何運行。 甚至 Python 自己依靠使用本身的擴展點實現了不少額外的特性 — 這些不須要改變語法或者解釋器。

對象

屬性(在C#中通常翻譯成特性)存取是我喜歡舉的一個簡單例子。在 Java 中,一個 Point 類可能選擇用 getX() 和 setX() 方法而不是一個簡單直白的 x 屬性。緣由是若是你須要改變 x 的讀或寫,你不須要破壞接口。在 Python 中,你不須要擔憂前面的這些, 由於必要時你能解釋屬性存取。

class Point:

def __init__(self, x, y):

self._x = x

self._y = y

@property

def x(self):

returnself._x

# ... samefory ...

point = Point(3, 4)

print(point.x)  # 3

有趣的 @property 語法是一種修飾,看來就像 Java 的註解,但它能夠更直接地修改函數或類。這是徹底透明的調用代碼——和讀其它屬性沒什麼區別——可是對象能夠根據本身的須要干預或處理它。與 Java 不一樣,屬性訪問是類 API 的一部分,能夠自由的定義。(注意這個示例讓 x 成爲只讀的,由於我沒有指定寫方法!可寫屬性的語法有點滑稽,這裏暫時無論它如何工做。但你能夠具體規定只有奇數能夠賦值給 point.x。)

這個特性也存在於其它靜態語言中,好比 C#,因此這並非什麼大不了的東西。關於 Python 真正有趣的部分是,屬性並沒什麼特別。它是一個正常的內建類型,一段純粹並且不滿一屏的 Python 程序。它的工做原理是 Python 類能夠自定義其屬性訪問,包括通常的和按屬性的。包裝、代理和組合很容易實現:你能夠將全部訪問調用轉發到底層對象,而沒必要知道它有什麼方法。

相同的鉤子屬性可用於懶加載屬性或者自動持有弱引用的屬性——這對調用代碼徹底透明,經過純 Python 就能實現。

你可能已經注意到個人代碼沒有使用 public 或 private 修飾符。事實上,Python 中不存在這個概念。按照慣例,用一個下劃線開頭表示「私有」——或者更準備地說,「不打算成爲穩定公開 API 的一部分」。但這並無語言上的意義,Phthon 自己不會阻止偵查或修改這樣的屬性(若是是方法的話,則是調用)。一樣,也沒有final 、static或const。

這是一樣的工做原理:核心 Python 一般不會妨礙你作任何事情。若是你須要,它會很是有用。我已經經過啓動時調用或重寫,甚至從新定義私有方法來修補第三方庫的 BUG。這樣我不須要從新作一個項目的本地分支,能夠省很多事。並且一量官方修復了 BUG,可很容易就能刪掉本身的補丁代碼。

一樣,你能夠輕鬆地編寫依賴外部狀態的測試代碼——好比當前時間。若是重構不可行,你能夠在測試時把 time.time() 替換爲模擬函數。庫函數只是模塊模塊的屬性(就像 Java 的包),並且 Python 模塊是種對象,和其它對象同樣,因此它們能夠以一樣的方式偵查到或被修改。

Java 的類由 Class 對象支持,但兩者並不有徹底互換。好比 Foo 類的 Class 對象是 Foo.class。我不認爲 Foo 能夠被它本身使用,由於它命名了一個類型,Java 在處理類型和值的時候會有一些微妙的區別。

Python 中,類是對象,是類型的實例(它自己就是對象,是它本身的實例,想起來頗有趣。)類能夠看成其它值同樣使用:做爲參數、保存一某個更大的數據結構中、檢查、操做。有時候把類做爲字典的鍵特別有用。並且由於類是實例化的,能夠簡單地調用它們——Python 沒有 new 關鍵字 —— 不少狀況下 new 和簡單的函數調用能夠互換。這樣一來,一些常見的模式,好比工廠模式,就太簡單了,幾乎不須要。

# 等等,Vehicle 是一個類仍是一個工廠函數?誰管呢!

# 就算它在類或工廠函數之間互換,也不會破壞這段代碼。

car = Vehicle(wheels=4, doors=4)

最近我好幾回把函數甚至常規代碼放在頂層,不在任何類裏面。這樣作不會有問題,可是其含義有點微妙。Python 中甚至 class 和 def 都是常規代碼,在運行的時候執行。Python 文件從上往下執行,class 和 def 並不特別。它們只是有特殊的語法,用來建立特定類型的對象:類和函數。

如下是真正酷的部分。類是對象,它們的類型是type,所以你能夠子類化並改變它的運行。而後,你能夠生成你的子類的實例。

第一次接觸仔細想一想會感受有點奇怪。可是再想下,你獲益於不須要知道它是如何運行的。好比,Python沒有enum塊,但它確實有 enum module:

class Animal(Enum):

cat = 0

dog = 1

mouse = 2

snake = 3

print(Animal.cat)           #

print(Animal.cat.value)     # 0

print(Animal(2))            #

print(Animal['dog'])        #

class 語句建立了一個對象,這意味着它在某處調用了構造函數,並且能夠重寫該構造函數來改變類的構造方式。這裏Enum建立了一個固定的實例集,而不是類屬性。全部這些都是用普通的 Python 代碼的常規的 Python 語法實現的。

實體庫也是基於這個思路來構建的。你討厭在構造函數中單調的幹 self.foo = foo 這種事情嗎?而後純手工定義相等性比較、哈希和克隆和開發可讀的列表?Java 須要編譯器支持,這個支持可能來自 Amber 項目。Python 很是靈活,因此社區中有 attrs 庫解決了這個問題。

import attr

@attr.s

class Point:

x = attr.ib()

y = attr.ib()

p = Point(3, 4)

q = Point(x=3, y=4)

p == q  #True, which it wouldn't have been before!

print(p)  # Point(x=3, y=4)

或者採用 SQLAlchemy 這個功能強大的 Python 數據庫封裝庫。它包含一個靈感來自 Hibernate 的 ORM,但不須要在配置文件裏定義表結構或者經過其餘冗長的註解,你可直接在類裏編寫數據庫映射代碼:

classOrder(Table):

id =Column(Integer, primary_key=True)

order_number =Column(Integer,index=True)

status =Column(Enum('pending','complete'),default='pending')

...

它的基本思想類同Enum,但SQLAlchemy也使用和property一樣的鉤子,天然而然地,你能夠修改欄位值。

order.order_number = 5

session.commit()

最後,類自己能夠在運行中被建立。 這有點好處,但是 thriftpy 建立的整個 module, 裏面全是基於 Thrift 定義文件的類。 在Java中,你得須要代碼生成,這就增長了全新的編譯步驟,從而致使不一樣步。

全部這些示例依賴於Python現存的語法,但也在裏面吸取了新的含義。它能作的,沒有你在Java或者其餘語言中不能作的。但它刪減告終構性的重複 — 正是這些使得編碼更易寫、易讀,以及產生更少的bug。

結語

Python 有不少和Java相同的基本概念,但處理方向很是不一樣,它加入了一些全新的思想。Java關注於穩定性和可靠性,而Python關注於可表達性和靈活性。它是一種徹底不一樣的思想方式來思考命令式編程。

我有理由相信Python將讓你在Java所擅長的領域替換Java。Python可能不會贏在速度競賽上,好比(Pypy,一種即時編譯的Python)。Java擁有對線程的原生支持,而Python界大都回避了這些問題。規模龐大複雜又有不少死角的軟件更喜歡靜態類型提供的合理性檢查(好比mypy,一種Python靜態類型檢查器)。

也許某些 Java 並不擅長的領域恰好是 Python 的強項。例如大量的軟件對性能的要求並不高,也不須要並行執行,咱們只須要考慮具體實現業務的問題。我發現使用 Python 開始一個項目很是簡單並且快速。沒有單獨的編譯過程,編碼而後運行的速度很是快。代碼很簡短,這也意味着代碼更容易被理解。嘗試不一樣的架構方法看起來更加容易。並且有時候嘗試一些愚蠢的想法是如此的有趣,就好像 使用庫實現 goto 功能。

我但願你能試試 Python ,自從我用了它以後,已經從中得到不少樂趣,我相信你也同樣。至少不用刻意的去拒絕它。

最壞的狀況,還有個 Pyjnius 可讓你這樣作:

fromjnius import autoclass

System = autoclass('java.lang.System')

System.out.println('Hello, world!')


最後,每一位讀到這裏的網友,感謝大家能耐心地看完。以爲對你有幫助能夠給個喜歡!但願在成爲一名更優秀的Java程序員的道路上,咱們能夠一塊兒學習、一塊兒進步

相關文章
相關標籤/搜索