国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目錄
從解釋器的角度看對象的調(diào)用
下面我們可以做總結(jié)了,通過類型對象去創(chuàng)建實例對象的整體流程如下:
首頁 后端開發(fā) Python教程 源碼探秘:Python 中對象是如何被調(diào)用的?

源碼探秘:Python 中對象是如何被調(diào)用的?

May 11, 2023 am 11:46 AM
python 對象 調(diào)用

源碼探秘:Python 中對象是如何被調(diào)用的?

楔子

我們知道對象被創(chuàng)建,主要有兩種方式,一種是通過Python/C API,另一種是通過調(diào)用類型對象。對于內(nèi)置類型的實例對象而言,這兩種方式都是支持的,比如列表,我們即可以通過[]創(chuàng)建,也可以通過list(),前者是Python/C API,后者是調(diào)用類型對象。

但對于自定義類的實例對象而言,我們只能通過調(diào)用類型對象的方式來創(chuàng)建。而一個對象如果可以被調(diào)用,那么這個對象就是callable,否則就不是callable。

而決定一個對象是不是callable,就取決于其對應的類型對象中是否定義了某個方法。如果從 Python 的角度看的話,這個方法就是 __call__,從解釋器角度看的話,這個方法就是 tp_call。

從 Python 的角度看對象的調(diào)用

調(diào)用 int、str、tuple 可以創(chuàng)建一個整數(shù)、字符串、元組,調(diào)用自定義的類也可以創(chuàng)建出相應的實例對象,說明類型對象是可調(diào)用的,也就是callable。那么這些類型對象(int、str、tuple、class等等)的類型對象(type)內(nèi)部一定有 __call__ 方法。

# int可以調(diào)用
# 那么它的類型對象、也就是元類(type), 內(nèi)部一定有__call__方法
print(hasattr(type, "__call__"))# True
# 而調(diào)用一個對象,等價于調(diào)用其類型對象的 __call__ 方法
# 所以 int(3.14)實際就等價于如下
print(type.__call__(int, 3.14))# 3

注意:這里描述的可能有一些繞,我們說 int、str、float 這些都是類型對象(簡單來說就是類),而 123、"你好"、3.14 是其對應的實例對象,這些都沒問題。但type是不是類型對象,顯然是的,雖然我們稱呼它為元類,但它也是類型對象,如果 print(type) 顯示的也是一個類。

那么相對 type 而言,int、str、float 是不是又成了實例對象呢?因為它們的類型是 type。

所以 class 具有二象性:

  • 如果站在實例對象(如:123、"satori"、[]、3.14)的角度上,它是類型對象
  • 如果站在 type 的角度上,它是實例對象

同理 type 的類型是也是 type,那么 type 既是 type 的類型對象,type 也是 type 的實例對象。雖然這里描述的會有一些繞,但應該不難理解,并且為了避免后續(xù)的描述出現(xiàn)歧義,這里我們做一個申明:

  • 整數(shù)、浮點數(shù)、字符串等等,我們稱之為實例對象
  • int、float、str、dict,以及我們自定義的類,我們稱之為類型對象
  • type 雖然也是類型對象,但我們稱它為元類

所以 type 的內(nèi)部有 __call__ 方法,那么說明類型對象都是可調(diào)用的,因為調(diào)用類型對象就是調(diào)用 type 的 __call__ 方法。而實例對象能否調(diào)用就不一定了,這取決于它的類型對象中是否定義了 __call__ 方法,因為調(diào)用一個對象,本質(zhì)上是執(zhí)行其類型對象內(nèi)部的 __call__ 方法。

class A:
 pass
a = A()
# 因為我們自定義的類 A 里面沒有 __call__
# 所以 a 是不可以被調(diào)用的
try:
 a()
except Exception as e:
 # 告訴我們 A 的實例對象不可以被調(diào)用
 print(e)# 'A' object is not callable
# 如果我們給 A 設(shè)置了一個 __call__
type.__setattr__(A, "__call__", lambda self: "這是__call__")
# 發(fā)現(xiàn)可以調(diào)用了
print(a())# 這是__call__

我們看到這就是動態(tài)語言的特性,即便在類創(chuàng)建完畢之后,依舊可以通過type進行動態(tài)設(shè)置,而這在靜態(tài)語言中是不支持的。所以type是所有類的元類,它控制了我們自定義類的生成過程,type這個古老而又強大的類可以讓我們玩出很多新花樣。

但是對于內(nèi)置的類,type是不可以對其動態(tài)增加、刪除或者修改屬性的,因為內(nèi)置的類在底層是靜態(tài)定義好的。因為從源碼中我們看到,這些內(nèi)置的類、包括元類,它們都是PyTypeObject對象,在底層已經(jīng)被聲明為全局變量了,或者說它們已經(jīng)作為靜態(tài)類存在了。所以type雖然是所有類型對象的元類,但是只有在面對我們自定義的類,type才具有增刪改的能力。

而且我們也解釋過,Python 的動態(tài)性是解釋器將字節(jié)碼翻譯成 C 代碼的時候動態(tài)賦予的,因此給類動態(tài)設(shè)置屬性或方法只適用于動態(tài)類,也就是在 py 文件中使用 class 關(guān)鍵字定義的類。

而對于靜態(tài)類、或者編寫擴展模塊時定義的擴展類(兩者是等價的),它們在編譯之后已經(jīng)是指向 C 一級的數(shù)據(jù)結(jié)構(gòu)了,不需要再被解釋器解釋了,因此解釋器自然也就無法在它們身上動手腳,畢竟彪悍的人生不需要解釋。

try:
 type.__setattr__(dict, "__call__", lambda self: "這是__call__")
except Exception as e:
 print(e)# can't set attributes of built-in/extension type 'dict'

我們看到拋異常了,提示我們不可以給內(nèi)置/擴展類型dict設(shè)置屬性,因為它們繞過了解釋器解釋執(zhí)行這一步,所以其屬性不能被動態(tài)設(shè)置。

同理其實例對象亦是如此,靜態(tài)類的實例對象也不可以動態(tài)設(shè)置屬性:

class Girl:
 pass
g = Girl()
g.name = "古明地覺"
# 實例對象我們也可以手動設(shè)置屬性
print(g.name)# 古明地覺
lst = list()
try:
 lst.name = "古明地覺"
except Exception as e:
 # 但是內(nèi)置類型的實例對象是不可以的
 print(e)# 'list' object has no attribute 'name'

可能有人奇怪了,為什么列表不行呢?答案是內(nèi)置類型的實例對象沒有__dict__屬性字典,因為相關(guān)屬性或方法底層已經(jīng)定義好了,不可以動態(tài)添加。如果我們自定義類的時候,設(shè)置了__slots__,那么效果和內(nèi)置的類是相同的。

當然了,我們后面會介紹如何通過動態(tài)修改解釋器來改變這一點,舉個栗子,不是說靜態(tài)類無法動態(tài)設(shè)置屬性嗎?下面我就來打自己臉:

import gc
try:
 type.__setattr__(list, "ping", "pong")
except TypeError as e:
 print(e)# can't set attributes of built-in/extension type 'list'
# 我們看到無法設(shè)置,那么我們就來改變這一點
attrs = gc.get_referents(tuple.__dict__)[0]
attrs["ping"] = "pong"
print(().ping)# pong
attrs["append"] = lambda self, item: self + (item,)
print(
 ().append(1).append(2).append(3)
)# (1, 2, 3)

我臉腫了。好吧,其實這只是我們玩的一個小把戲,當我們介紹完整個 CPython 的時候,會來專門聊一聊如何動態(tài)修改解釋器。比如:讓元組變得可修改,讓 Python 真正利用多核等等。

從解釋器的角度看對象的調(diào)用

我們以內(nèi)置類型 float 為例,我們說創(chuàng)建一個 PyFloatObject,可以通過3.14或者float(3.14)的方式。前者使用Python/C API創(chuàng)建,3.14直接被解析為 C 一級數(shù)據(jù)結(jié)構(gòu),也就是PyFloatObject實例;后者使用類型對象創(chuàng)建,通過對float進行一個調(diào)用、將3.14作為參數(shù),最終也得到指向C一級數(shù)據(jù)結(jié)構(gòu)PyFloatObject實例。

Python/C API的創(chuàng)建方式我們已經(jīng)很清晰了,就是根據(jù)值來推斷在底層應該對應哪一種數(shù)據(jù)結(jié)構(gòu),然后直接創(chuàng)建即可。我們重點看一下通過類型調(diào)用來創(chuàng)建實例對象的方式。

如果一個對象可以被調(diào)用,它的類型對象中一定要有tp_call(更準確的說成員tp_call的值是一個函數(shù)指針,不可以是0),而PyFloat_Type是可以調(diào)用的,這就說明PyType_Type內(nèi)部的tp_call是一個函數(shù)指針,這在Python的層面上我們已經(jīng)驗證過了,下面我們再來通過源碼看一下。

//typeobject.c
PyTypeObject PyType_Type = {
 PyVarObject_HEAD_INIT(&PyType_Type, 0)
 "type", /* tp_name */
 sizeof(PyHeapTypeObject), /* tp_basicsize */
 sizeof(PyMemberDef),/* tp_itemsize */
 (destructor)type_dealloc, /* tp_dealloc */
 //... /* tp_hash */
 (ternaryfunc)type_call, /* tp_call */
 //...
}

我們看到在實例化PyType_Type的時候PyTypeObject內(nèi)部的成員tp_call被設(shè)置成了type_call。這是一個函數(shù)指針,當我們調(diào)用PyFloat_Type的時候,會觸發(fā)這個type_call指向的函數(shù)。

因此 float(3.14) 在C的層面上等價于:

(&PyFloat_Type) -> ob_type -> tp_call(&PyFloat_Type, args, kwargs);
// 即:
(&PyType_Type) -> tp_call(&PyFloat_Type, args, kwargs);
// 而在創(chuàng)建 PyType_Type 的時候,給 tp_call 成員傳遞的是 type_call
// 因此最終相當于
type_call(&PyFloat_Type, args, kwargs)

如果用 Python 來演示這一過程的話:

# float(3.14),等價于
f1 = float.__class__.__call__(float, 3.14)
# 等價于
f2 = type.__call__(float, 3.14)
print(f1, f2)# 3.14 3.14

這就是 float(3.14) 的秘密,相信list、dict在實例化的時候是怎么做的,你已經(jīng)猜到了,做法是相同的。

# lst = list("abcd")
lst = list.__class__.__call__(list, "abcd")
print(lst)# ['a', 'b', 'c', 'd']
# dct = dict([("name", "古明地覺"), ("age", 17)])
dct = dict.__class__.__call__(dict, [("name", "古明地覺"), ("age", 17)])
print(dct)# {'name': '古明地覺', 'age': 17}

最后我們來圍觀一下 type_call 函數(shù),我們說 type 的 __call__ 方法,在底層對應的是 type_call 函數(shù),它位于Object/typeobject.c中。

static PyObject *
type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
 // 如果我們調(diào)用的是 float
 // 那么顯然這里的 type 就是 &PyFloat_Type

 // 這里是聲明一個PyObject *
 // 顯然它是要返回的實例對象的指針
 PyObject *obj;

 // 這里會檢測 tp_new是否為空,tp_new是什么估計有人已經(jīng)猜到了
 // 我們說__call__對應底層的tp_call
 // 顯然__new__對應底層的tp_new,這里是為實例對象分配空間
 if (type->tp_new == NULL) {
 // tp_new 是一個函數(shù)指針,指向具體的構(gòu)造函數(shù)
 // 如果 tp_new 為空,說明它沒有構(gòu)造函數(shù)
 // 因此會報錯,表示無法創(chuàng)建其實例
 PyErr_Format(PyExc_TypeError,
"cannot create '%.100s' instances",
type->tp_name);
 return NULL;
 }

 //通過tp_new分配空間
 //此時實例對象就已經(jīng)創(chuàng)建完畢了,這里會返回其指針
 obj = type->tp_new(type, args, kwds);
 //類型檢測,暫時不用管
 obj = _Py_CheckFunctionResult((PyObject*)type, obj, NULL);
 if (obj == NULL)
 return NULL;
 //我們說這里的參數(shù)type是類型對象,但也可以是元類
 //元類也是由PyTypeObject結(jié)構(gòu)體實例化得到的
 //元類在調(diào)用的時候執(zhí)行的依舊是type_call
 //所以這里是檢測type指向的是不是PyType_Type
 //如果是的話,那么實例化得到的obj就不是實例對象了,而是類型對象
 //要單獨檢測一下
 if (type == &PyType_Type &&
 PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
 (kwds == NULL ||
(PyDict_Check(kwds) && PyDict_GET_SIZE(kwds) == 0)))
 return obj;
 //tp_new應該返回相應類型對象的實例對象(的指針)
 //但如果不是,就直接將這里的obj返回
 //此處這么做可能有點難理解,我們一會細說
 if (!PyType_IsSubtype(Py_TYPE(obj), type))
 return obj;

 //拿到obj的類型
 type = Py_TYPE(obj);
 //執(zhí)行 tp_init
 //顯然這個tp_init就是__init__函數(shù)
 //這與Python中類的實例化過程是一致的。
 if (type->tp_init != NULL) {
 //將tp_new返回的對象作為self,執(zhí)行 tp_init
 int res = type->tp_init(obj, args, kwds);
 if (res < 0) {
 //執(zhí)行失敗,將引入計數(shù)減1,然后將obj設(shè)置為NULL
 assert(PyErr_Occurred());
 Py_DECREF(obj);
 obj = NULL;
 }
 else {
 assert(!PyErr_Occurred());
 }
 }
 //返回obj
 return obj;
}

因此從上面我們可以看到關(guān)鍵的部分有兩個:

  • 調(diào)用類型對象的 tp_new 指向的函數(shù)為實例對象申請內(nèi)存
  • 調(diào)用 tp_init 指向的函數(shù)為實例對象進行初始化,也就是設(shè)置屬性

所以這對應Python中的__new__和__init__,我們說__new__是為實例對象開辟一份內(nèi)存,然后返回指向這片內(nèi)存(對象)的指針,并且該指針會自動傳遞給__init__中的self。

class Girl:
 def __new__(cls, name, age):
 print("__new__方法執(zhí)行啦")
 # 寫法非常固定
 # 調(diào)用object.__new__(cls)就會創(chuàng)建Girl的實例對象
 # 因此這里的cls指的就是這里的Girl,注意:一定要返回
 # 因為__new__會將自己的返回值交給__init__中的self
 return object.__new__(cls)
 def __init__(self, name, age):
 print("__init__方法執(zhí)行啦")
 self.name = name
 self.age = age
g = Girl("古明地覺", 16)
print(g.name, g.age)
"""
__new__方法執(zhí)行啦
__init__方法執(zhí)行啦
古明地覺 16
"""

__new__里面的參數(shù)要和__init__里面的參數(shù)保持一致,因為我們會先執(zhí)行__new__,然后解釋器會將__new__的返回值和我們傳遞的參數(shù)組合起來一起傳遞給__init__。因此__new__里面的參數(shù)除了cls之外,一般都會寫*args和**kwargs。

然后再回過頭來看一下type_call中的這幾行代碼:

static PyObject *
type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
 //......
 //......
 if (!PyType_IsSubtype(Py_TYPE(obj), type))
 return obj;

 //......
 //......
}

我們說tp_new應該返回該類型對象的實例對象,而且一般情況下我們是不寫__new__的,會默認執(zhí)行。但是我們一旦重寫了,那么必須要手動返回object.__new__(cls)。可如果我們不返回,或者返回其它的話,會怎么樣呢?

class Girl:
 def __new__(cls, *args, **kwargs):
 print("__new__方法執(zhí)行啦")
 instance = object.__new__(cls)
 # 打印看看instance到底是個什么東東
 print("instance:", instance)
 print("type(instance):", type(instance))

 # 正確做法是將instance返回
 # 但是我們不返回, 而是返回個 123
 return 123
 def __init__(self, name, age):
 print("__init__方法執(zhí)行啦")
g = Girl()
"""
__new__方法執(zhí)行啦
instance: <__main__.Girl object at 0x000002C0F16FA1F0>
type(instance): <class '__main__.Girl'>
"""

這里面有很多可以說的點,首先就是 __init__ 里面需要兩個參數(shù),但是我們沒有傳,卻還不報錯。原因就在于這個 __init__ 壓根就沒有執(zhí)行,因為 __new__ 返回的不是 Girl 的實例對象。

通過打印 instance,我們知道了object.__new__(cls) 返回的就是 cls 的實例對象,而這里的cls就是Girl這個類本身。我們必須要返回instance,才會執(zhí)行對應的__init__,否則__new__直接就返回了。我們在外部來打印一下創(chuàng)建的實例對象吧,看看結(jié)果:

class Girl:
 def __new__(cls, *args, **kwargs):
 return 123
 def __init__(self, name, age):
 print("__init__方法執(zhí)行啦")
g = Girl()
print(g, type(g))# 123 <class 'int'>

我們看到打印的是123,所以再次總結(jié)一些tp_new和tp_init之間的區(qū)別,當然也對應__new__和__init__的區(qū)別:

  • tp_new:為該類型對象的實例對象申請內(nèi)存,在Python的__new__方法中通過object.__new__(cls)的方式申請,然后將其返回
  • tp_init:tp_new的返回值會自動傳遞給self,然后為self綁定相應的屬性,也就是進行實例對象的初始化

但如果tp_new返回的不是對應類型的實例對象的指針,比如type_call中第一個參數(shù)接收的&PyFloat_Type,但是tp_new中返回的卻是PyLongObject *,所以此時就不會執(zhí)行tp_init。

以上面的代碼為例,我們Girl中的__new__應該返回Girl的實例對象才對,但實際上返回了整型,因此類型不一致,所以不會執(zhí)行__init__。

下面我們可以做總結(jié)了,通過類型對象去創(chuàng)建實例對象的整體流程如下:

  • 第一步:獲取類型對象的類型對象,說白了就是元類,執(zhí)行元類的 tp_call 指向的函數(shù),即 type_call
  • 第二步:type_call 會調(diào)用該類型對象的 tp_new 指向的函數(shù),如果 tp_new 為 NULL,那么會到 tp_base 指定的父類里面去尋找 tp_new。在新式類當中,所有的類都繼承自 object,因此最終會執(zhí)行 object 的 __new__。然后通過訪問對應類型對象中的 tp_basicsize 信息,這個信息記錄著該對象的實例對象需要占用多大的內(nèi)存,繼而完成申請內(nèi)存的操作
  • 調(diào)用type_new 創(chuàng)建完對象之后,就會進行實例對象的初始化,會將指向這片空間的指針交給 tp_init,但前提是 tp_new 返回的實例對象的類型要一致。

所以都說 Python 在實例化的時候會先調(diào)用 __new__ 方法,再調(diào)用 __init__ 方法,相信你應該知道原因了,因為在源碼中先調(diào)用 tp_new、再調(diào)用的 tp_init。

static PyObject *
type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
 //調(diào)用__new__方法, 拿到其返回值
 obj = type->tp_new(type, args, kwds);
 if (type->tp_init != NULL) {
 //將__new__返回的實例obj,和args、kwds組合起來
 //一起傳給 __init__
 //其中 obj 會傳給 self,
 int res = type->tp_init(obj, args, kwds);
 //......
 return obj;
}

所以源碼層面表現(xiàn)出來的,和我們在 Python 層面看到的是一樣的。

小結(jié)

到此,我們就從 Python 和解釋器兩個層面了解了對象是如何調(diào)用的,更準確的說我們是從解釋器的角度對 Python 層面的知識進行了驗證,通過 tp_new 和 tp_init 的關(guān)系,來了解 __new__ 和 __init__ 的關(guān)系。

另外,對象調(diào)用遠不止我們目前說的這么簡單,更多的細節(jié)隱藏在了幕后,只不過現(xiàn)在沒辦法將其一次性全部挖掘出來。

以上是源碼探秘:Python 中對象是如何被調(diào)用的?的詳細內(nèi)容。更多信息請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻,版權(quán)歸原作者所有,本站不承擔相應法律責任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動的應用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機

Video Face Swap

Video Face Swap

使用我們完全免費的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級代碼編輯軟件(SublimeText3)

熱門話題

Laravel 教程
1601
29
PHP教程
1502
276
PHP調(diào)用AI智能語音助手 PHP語音交互系統(tǒng)搭建 PHP調(diào)用AI智能語音助手 PHP語音交互系統(tǒng)搭建 Jul 25, 2025 pm 08:45 PM

用戶語音輸入通過前端JavaScript的MediaRecorderAPI捕獲并發(fā)送至PHP后端;2.PHP將音頻保存為臨時文件后調(diào)用STTAPI(如Google或百度語音識別)轉(zhuǎn)換為文本;3.PHP將文本發(fā)送至AI服務(如OpenAIGPT)獲取智能回復;4.PHP再調(diào)用TTSAPI(如百度或Google語音合成)將回復轉(zhuǎn)為語音文件;5.PHP將語音文件流式返回前端播放,完成交互。整個流程由PHP主導數(shù)據(jù)流轉(zhuǎn)與錯誤處理,確保各環(huán)節(jié)無縫銜接。

如何用PHP結(jié)合AI實現(xiàn)文本糾錯 PHP語法檢測與優(yōu)化 如何用PHP結(jié)合AI實現(xiàn)文本糾錯 PHP語法檢測與優(yōu)化 Jul 25, 2025 pm 08:57 PM

要實現(xiàn)PHP結(jié)合AI進行文本糾錯與語法優(yōu)化,需按以下步驟操作:1.選擇適合的AI模型或API,如百度、騰訊API或開源NLP庫;2.通過PHP的curl或Guzzle調(diào)用API并處理返回結(jié)果;3.在應用中展示糾錯信息并允許用戶選擇是否采納;4.使用php-l和PHP_CodeSniffer進行語法檢測與代碼優(yōu)化;5.持續(xù)收集反饋并更新模型或規(guī)則以提升效果。選擇AIAPI時應重點評估準確率、響應速度、價格及對PHP的支持。代碼優(yōu)化應遵循PSR規(guī)范、合理使用緩存、避免循環(huán)查詢、定期審查代碼,并借助X

python seaborn關(guān)節(jié)圖示例 python seaborn關(guān)節(jié)圖示例 Jul 26, 2025 am 08:11 AM

使用Seaborn的jointplot可快速可視化兩個變量間的關(guān)系及各自分布;2.基礎(chǔ)散點圖通過sns.jointplot(data=tips,x="total_bill",y="tip",kind="scatter")實現(xiàn),中心為散點圖,上下和右側(cè)顯示直方圖;3.添加回歸線和密度信息可用kind="reg",并結(jié)合marginal_kws設(shè)置邊緣圖樣式;4.數(shù)據(jù)量大時推薦kind="hex",用

PHP集成AI情感計算技術(shù) PHP用戶反饋智能分析 PHP集成AI情感計算技術(shù) PHP用戶反饋智能分析 Jul 25, 2025 pm 06:54 PM

要將AI情感計算技術(shù)融入PHP應用,核心是利用云服務AIAPI(如Google、AWS、Azure)進行情感分析,通過HTTP請求發(fā)送文本并解析返回的JSON結(jié)果,將情感數(shù)據(jù)存入數(shù)據(jù)庫,從而實現(xiàn)用戶反饋的自動化處理與數(shù)據(jù)洞察。具體步驟包括:1.選擇適合的AI情感分析API,綜合考慮準確性、成本、語言支持和集成復雜度;2.使用Guzzle或curl發(fā)送請求,存儲情感分數(shù)、標簽及強度等信息;3.構(gòu)建可視化儀表盤,支持優(yōu)先級排序、趨勢分析、產(chǎn)品迭代方向和用戶細分;4.應對技術(shù)挑戰(zhàn),如API調(diào)用限制、數(shù)

python列表到字符串轉(zhuǎn)換示例 python列表到字符串轉(zhuǎn)換示例 Jul 26, 2025 am 08:00 AM

字符串列表可用join()方法合并,如''.join(words)得到"HelloworldfromPython";2.數(shù)字列表需先用map(str,numbers)或[str(x)forxinnumbers]轉(zhuǎn)為字符串后才能join;3.任意類型列表可直接用str()轉(zhuǎn)換為帶括號和引號的字符串,適用于調(diào)試;4.自定義格式可用生成器表達式結(jié)合join()實現(xiàn),如'|'.join(f"[{item}]"foriteminitems)輸出"[a]|[

python pandas融化示例 python pandas融化示例 Jul 27, 2025 am 02:48 AM

pandas.melt()用于將寬格式數(shù)據(jù)轉(zhuǎn)為長格式,答案是通過指定id_vars保留標識列、value_vars選擇需融化的列、var_name和value_name定義新列名,1.id_vars='Name'表示Name列不變,2.value_vars=['Math','English','Science']指定要融化的列,3.var_name='Subject'設(shè)置原列名的新列名,4.value_name='Score'設(shè)置原值的新列名,最終生成包含Name、Subject和Score三列

優(yōu)化用于內(nèi)存操作的Python 優(yōu)化用于內(nèi)存操作的Python Jul 28, 2025 am 03:22 AM

pythoncanbeoptimizedFormized-formemory-boundoperationsbyreducingOverHeadThroughGenerator,有效dattratsures,andManagingObjectLifetimes.first,useGeneratorSInsteadoFlistSteadoflistSteadoFocessLargedAtasetSoneItematatime,desceedingingLoadeGingloadInterveringerverneDraineNterveingerverneDraineNterveInterveIntMory.second.second.second.second,Choos,Choos

Python連接到SQL Server PYODBC示例 Python連接到SQL Server PYODBC示例 Jul 30, 2025 am 02:53 AM

安裝pyodbc:使用pipinstallpyodbc命令安裝庫;2.連接SQLServer:通過pyodbc.connect()方法,使用包含DRIVER、SERVER、DATABASE、UID/PWD或Trusted_Connection的連接字符串,分別支持SQL身份驗證或Windows身份驗證;3.查看已安裝驅(qū)動:運行pyodbc.drivers()并篩選含'SQLServer'的驅(qū)動名,確保使用如'ODBCDriver17forSQLServer'等正確驅(qū)動名稱;4.連接字符串關(guān)鍵參數(shù)

See all articles