最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Python+PyQt+MVVM方式開發(fā)桌面應用

 更新時間:2026年05月18日 08:36:01   作者:yuanpan  
本文通過一個簡單的待辦事項小工具,介紹了使用Python和PyQt6實現(xiàn)MVVM架構的方法,文章詳細解釋了什么是MVVM,并展示了如何將項目分為Model、View和ViewModel三層,從而使代碼更加清晰、可維護,文中還提供了項目結構建議、代碼示例和安裝方法,需要的朋友可以參考下

很多 Python 開發(fā)者第一次寫 PyQt 桌面應用時,代碼很容易變成這樣:

  • 按鈕點擊邏輯寫在窗口類里。
  • 數(shù)據(jù)處理也寫在窗口類里。
  • 數(shù)據(jù)校驗、狀態(tài)刷新、列表更新都寫在窗口類里。
  • 項目越寫越大,最后 MainWindow 變成幾千行。

小 demo 這樣寫沒問題,但如果你要做一個長期維護的桌面應用,比如數(shù)據(jù)處理工具、內部管理軟件、設備控制客戶端、圖像處理工具,就需要更清晰的代碼組織方式。

這篇文章用一個簡單的待辦事項小工具,帶大家入門 Python + PyQt6 + MVVM 的開發(fā)方式。

說明:本文使用 PyQt6 演示。根據(jù) PyPI 頁面,PyQt6 是 Qt6 的 Python 綁定,截至 2026-04-22 可見的最新版本為 6.11.0,安裝要求 Python >=3.10。PyQt6 使用 GPL v3 或商業(yè)授權,正式商業(yè)項目請?zhí)崆按_認授權。

一、什么是 MVVM

MVVM 是 Model - View - ViewModel 的縮寫。

在桌面應用中,可以這樣理解:

負責什么不應該負責什么
Model業(yè)務數(shù)據(jù)、業(yè)務規(guī)則、數(shù)據(jù)結構不關心按鈕、窗口、控件
View窗口、按鈕、輸入框、列表等界面控件不寫復雜業(yè)務邏輯
ViewModel連接 View 和 Model,處理命令、狀態(tài)、校驗、通知界面刷新不直接依賴具體界面布局

簡單說:

  • Model 關心“數(shù)據(jù)是什么”。
  • View 關心“界面長什么樣”。
  • ViewModel 關心“界面操作后應該怎么改變數(shù)據(jù)和狀態(tài)”。

二、PyQt 里為什么適合用 MVVM

Qt 本身有兩個非常重要的機制:

  1. Signals / Slots:信號和槽,用來做對象之間的通信。
  2. Model / View:模型視圖機制,用來把數(shù)據(jù)和顯示控件分離。

Qt 官方文檔中提到,Model/View 架構用于管理數(shù)據(jù)與顯示方式之間的關系,數(shù)據(jù)變化可以通過信號通知視圖刷新。Signals/Slots 則是 Qt 對象之間通信的核心機制。

這兩個機制和 MVVM 很契合:

  • View 點擊按鈕,調用 ViewModel 的方法。
  • ViewModel 修改 Model。
  • ViewModel 通過信號通知 View 更新狀態(tài)。
  • View 使用 Qt 的 item model 顯示列表、表格、樹。

需要注意的是,Qt 里的 Model/View 和 MVVM 里的 Model 不是一回事:

  • MVVM 的 Model 是業(yè)務模型,比如 TodoItem、User、Order
  • Qt 的 QStandardItemModel、QAbstractListModel 是給界面控件顯示數(shù)據(jù)用的模型。

初學時先把這兩件事區(qū)分開,后面架構會清晰很多。

三、本文要做的演示程序

我們做一個簡單的待辦事項桌面應用:

功能包括:

  1. 輸入任務名稱。
  2. 點擊按鈕添加任務。
  3. 在列表中顯示任務。
  4. 雙擊任務切換完成狀態(tài)。
  5. 選中任務后可以刪除。
  6. 底部顯示統(tǒng)計信息。
  7. 輸入為空時給出提示。

這個功能不復雜,但足夠演示 MVVM 的基本分層。

四、項目結構

建議使用下面的目錄結構:

pyqt_mvvm_demo/
  requirements.txt
  main.py
  models/
    __init__.py
    todo_item.py
  viewmodels/
    __init__.py
    todo_list_view_model.py
  views/
    __init__.py
    main_window.py

每個目錄的職責:

文件職責
models/todo_item.py定義業(yè)務數(shù)據(jù)結構
viewmodels/todo_list_view_model.py管理任務列表、處理添加/刪除/切換完成狀態(tài)
views/main_window.py創(chuàng)建窗口和控件,綁定 ViewModel
main.py程序入口

五、安裝 PyQt6

先創(chuàng)建虛擬環(huán)境:

python -m venv .venv

Windows 激活:

.venv\Scripts\activate

macOS / Linux 激活:

source .venv/bin/activate

安裝 PyQt6:

pip install PyQt6

requirements.txt

PyQt6>=6.11.0

如果你的環(huán)境暫時不能安裝最新版本,也可以先不鎖版本:

PyQt6

六、編寫 Model:業(yè)務數(shù)據(jù)

創(chuàng)建 models/todo_item.py

from dataclasses import dataclass


@dataclass
class TodoItem:
    title: str
    done: bool = False

這個類非常簡單,只表達業(yè)務數(shù)據(jù):

  • title:任務標題。
  • done:是否完成。

它不關心界面,也不依賴 PyQt。

這就是 MVVM 里 Model 層應該保持的狀態(tài):干凈、簡單、可測試。

七、編寫 ViewModel:業(yè)務狀態(tài)和界面命令

創(chuàng)建 viewmodels/todo_list_view_model.py

from PyQt6.QtCore import QObject, Qt, pyqtSignal
from PyQt6.QtGui import QStandardItem, QStandardItemModel

from models.todo_item import TodoItem


class TodoListViewModel(QObject):
    message_changed = pyqtSignal(str)
    stats_changed = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self._items: list[TodoItem] = []
        self.list_model = QStandardItemModel()
        self.list_model.itemChanged.connect(self._on_item_changed)
        self._update_stats()

    def add_task(self, title: str) -> bool:
        title = title.strip()
        if not title:
            self.message_changed.emit("任務名稱不能為空")
            return False

        item = TodoItem(title=title)
        self._items.append(item)
        self._append_item_to_view_model(item)

        self.message_changed.emit(f"已添加任務:{title}")
        self._update_stats()
        return True

    def remove_task(self, row: int) -> None:
        if row < 0 or row >= len(self._items):
            self.message_changed.emit("請先選擇要刪除的任務")
            return

        removed = self._items.pop(row)
        self.list_model.removeRow(row)

        self.message_changed.emit(f"已刪除任務:{removed.title}")
        self._update_stats()

    def toggle_task(self, row: int) -> None:
        if row < 0 or row >= len(self._items):
            return

        item = self._items[row]
        item.done = not item.done

        qt_item = self.list_model.item(row)
        qt_item.setCheckState(
            Qt.CheckState.Checked if item.done else Qt.CheckState.Unchecked
        )

        self.message_changed.emit(
            f"已完成:{item.title}" if item.done else f"已取消完成:{item.title}"
        )
        self._update_stats()

    def _append_item_to_view_model(self, todo: TodoItem) -> None:
        qt_item = QStandardItem(todo.title)
        qt_item.setEditable(False)
        qt_item.setCheckable(True)
        qt_item.setCheckState(
            Qt.CheckState.Checked if todo.done else Qt.CheckState.Unchecked
        )
        qt_item.setData(todo, Qt.ItemDataRole.UserRole)
        self.list_model.appendRow(qt_item)

    def _on_item_changed(self, qt_item: QStandardItem) -> None:
        row = qt_item.row()
        if row < 0 or row >= len(self._items):
            return

        self._items[row].done = qt_item.checkState() == Qt.CheckState.Checked
        self._update_stats()

    def _update_stats(self) -> None:
        total = len(self._items)
        done = sum(1 for item in self._items if item.done)
        pending = total - done
        self.stats_changed.emit(f"總數(shù):{total},已完成:{done},未完成:{pending}")

這一層是本文最關鍵的部分。

ViewModel 做了幾件事:

  1. 保存業(yè)務數(shù)據(jù)列表:self._items。
  2. 提供給界面顯示的 Qt 模型:self.list_model
  3. 提供界面可調用的命令:add_task()、remove_task()、toggle_task()
  4. 通過信號告訴界面狀態(tài)變化:message_changed、stats_changed

ViewModel 不應該做的事:

  • 不創(chuàng)建窗口。
  • 不直接操作按鈕樣式。
  • 不關心控件放在第幾行第幾列。

這樣以后即使 View 從 QWidget 改成 QML,或者從桌面窗口改成別的界面形式,很多業(yè)務邏輯仍然可以復用。

八、編寫 View:窗口和控件

創(chuàng)建 views/main_window.py

from PyQt6.QtCore import QModelIndex
from PyQt6.QtWidgets import (
    QHBoxLayout,
    QLabel,
    QLineEdit,
    QListView,
    QMainWindow,
    QPushButton,
    QVBoxLayout,
    QWidget,
)

from viewmodels.todo_list_view_model import TodoListViewModel


class MainWindow(QMainWindow):
    def __init__(self, view_model: TodoListViewModel):
        super().__init__()
        self.view_model = view_model

        self.setWindowTitle("PyQt6 + MVVM 待辦事項")
        self.resize(520, 360)

        self.task_input = QLineEdit()
        self.task_input.setPlaceholderText("輸入任務名稱")

        self.add_button = QPushButton("添加")
        self.remove_button = QPushButton("刪除選中")
        self.remove_button.setEnabled(False)

        self.todo_list = QListView()
        self.todo_list.setModel(self.view_model.list_model)

        self.message_label = QLabel("請輸入任務名稱,然后點擊添加")
        self.stats_label = QLabel()

        self._build_layout()
        self._bind_events()
        self._bind_view_model()

    def _build_layout(self) -> None:
        input_layout = QHBoxLayout()
        input_layout.addWidget(self.task_input)
        input_layout.addWidget(self.add_button)

        button_layout = QHBoxLayout()
        button_layout.addStretch()
        button_layout.addWidget(self.remove_button)

        root_layout = QVBoxLayout()
        root_layout.addLayout(input_layout)
        root_layout.addWidget(self.todo_list)
        root_layout.addLayout(button_layout)
        root_layout.addWidget(self.stats_label)
        root_layout.addWidget(self.message_label)

        container = QWidget()
        container.setLayout(root_layout)
        self.setCentralWidget(container)

    def _bind_events(self) -> None:
        self.add_button.clicked.connect(self._on_add_clicked)
        self.task_input.returnPressed.connect(self._on_add_clicked)
        self.remove_button.clicked.connect(self._on_remove_clicked)
        self.todo_list.doubleClicked.connect(self._on_task_double_clicked)
        self.todo_list.selectionModel().currentChanged.connect(self._on_selection_changed)

    def _bind_view_model(self) -> None:
        self.view_model.message_changed.connect(self.message_label.setText)
        self.view_model.stats_changed.connect(self.stats_label.setText)

    def _on_add_clicked(self) -> None:
        ok = self.view_model.add_task(self.task_input.text())
        if ok:
            self.task_input.clear()
            self.task_input.setFocus()

    def _on_remove_clicked(self) -> None:
        row = self.todo_list.currentIndex().row()
        self.view_model.remove_task(row)

    def _on_task_double_clicked(self, index: QModelIndex) -> None:
        self.view_model.toggle_task(index.row())

    def _on_selection_changed(self, current: QModelIndex) -> None:
        self.remove_button.setEnabled(current.isValid())

View 層主要做三件事:

  1. 創(chuàng)建界面控件。
  2. 綁定控件事件。
  3. 綁定 ViewModel 的信號。

這里的窗口類沒有直接修改 _items,也沒有自己計算任務統(tǒng)計信息。它只負責把用戶操作轉交給 ViewModel。

這就是 MVVM 的核心思想:View 盡量薄,業(yè)務狀態(tài)放到 ViewModel。

九、編寫程序入口

創(chuàng)建 main.py

import sys

from PyQt6.QtWidgets import QApplication

from viewmodels.todo_list_view_model import TodoListViewModel
from views.main_window import MainWindow


def main() -> int:
    app = QApplication(sys.argv)

    view_model = TodoListViewModel()
    window = MainWindow(view_model)
    window.show()

    return app.exec()


if __name__ == "__main__":
    raise SystemExit(main())

運行:

python main.py

十、為了方便復制,這里給一個單文件版本

如果你只是想先跑起來,可以把下面代碼保存為 app.py。

import sys
from dataclasses import dataclass

from PyQt6.QtCore import QModelIndex, QObject, Qt, pyqtSignal
from PyQt6.QtGui import QStandardItem, QStandardItemModel
from PyQt6.QtWidgets import (
    QApplication,
    QHBoxLayout,
    QLabel,
    QLineEdit,
    QListView,
    QMainWindow,
    QPushButton,
    QVBoxLayout,
    QWidget,
)


@dataclass
class TodoItem:
    title: str
    done: bool = False


class TodoListViewModel(QObject):
    message_changed = pyqtSignal(str)
    stats_changed = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self._items: list[TodoItem] = []
        self.list_model = QStandardItemModel()
        self.list_model.itemChanged.connect(self._on_item_changed)
        self._update_stats()

    def add_task(self, title: str) -> bool:
        title = title.strip()
        if not title:
            self.message_changed.emit("任務名稱不能為空")
            return False

        todo = TodoItem(title=title)
        self._items.append(todo)

        qt_item = QStandardItem(todo.title)
        qt_item.setEditable(False)
        qt_item.setCheckable(True)
        qt_item.setCheckState(Qt.CheckState.Unchecked)
        qt_item.setData(todo, Qt.ItemDataRole.UserRole)
        self.list_model.appendRow(qt_item)

        self.message_changed.emit(f"已添加任務:{title}")
        self._update_stats()
        return True

    def remove_task(self, row: int) -> None:
        if row < 0 or row >= len(self._items):
            self.message_changed.emit("請先選擇要刪除的任務")
            return

        removed = self._items.pop(row)
        self.list_model.removeRow(row)
        self.message_changed.emit(f"已刪除任務:{removed.title}")
        self._update_stats()

    def toggle_task(self, row: int) -> None:
        if row < 0 or row >= len(self._items):
            return

        todo = self._items[row]
        todo.done = not todo.done

        qt_item = self.list_model.item(row)
        qt_item.setCheckState(
            Qt.CheckState.Checked if todo.done else Qt.CheckState.Unchecked
        )

        self.message_changed.emit(
            f"已完成:{todo.title}" if todo.done else f"已取消完成:{todo.title}"
        )
        self._update_stats()

    def _on_item_changed(self, qt_item: QStandardItem) -> None:
        row = qt_item.row()
        if row < 0 or row >= len(self._items):
            return

        self._items[row].done = qt_item.checkState() == Qt.CheckState.Checked
        self._update_stats()

    def _update_stats(self) -> None:
        total = len(self._items)
        done = sum(1 for item in self._items if item.done)
        pending = total - done
        self.stats_changed.emit(f"總數(shù):{total},已完成:{done},未完成:{pending}")


class MainWindow(QMainWindow):
    def __init__(self, view_model: TodoListViewModel):
        super().__init__()
        self.view_model = view_model

        self.setWindowTitle("PyQt6 + MVVM 待辦事項")
        self.resize(520, 360)

        self.task_input = QLineEdit()
        self.task_input.setPlaceholderText("輸入任務名稱")

        self.add_button = QPushButton("添加")
        self.remove_button = QPushButton("刪除選中")
        self.remove_button.setEnabled(False)

        self.todo_list = QListView()
        self.todo_list.setModel(self.view_model.list_model)

        self.stats_label = QLabel()
        self.message_label = QLabel("請輸入任務名稱,然后點擊添加")

        self._build_layout()
        self._bind_events()
        self._bind_view_model()

    def _build_layout(self) -> None:
        input_layout = QHBoxLayout()
        input_layout.addWidget(self.task_input)
        input_layout.addWidget(self.add_button)

        button_layout = QHBoxLayout()
        button_layout.addStretch()
        button_layout.addWidget(self.remove_button)

        root_layout = QVBoxLayout()
        root_layout.addLayout(input_layout)
        root_layout.addWidget(self.todo_list)
        root_layout.addLayout(button_layout)
        root_layout.addWidget(self.stats_label)
        root_layout.addWidget(self.message_label)

        container = QWidget()
        container.setLayout(root_layout)
        self.setCentralWidget(container)

    def _bind_events(self) -> None:
        self.add_button.clicked.connect(self._on_add_clicked)
        self.task_input.returnPressed.connect(self._on_add_clicked)
        self.remove_button.clicked.connect(self._on_remove_clicked)
        self.todo_list.doubleClicked.connect(self._on_task_double_clicked)
        self.todo_list.selectionModel().currentChanged.connect(self._on_selection_changed)

    def _bind_view_model(self) -> None:
        self.view_model.message_changed.connect(self.message_label.setText)
        self.view_model.stats_changed.connect(self.stats_label.setText)

    def _on_add_clicked(self) -> None:
        ok = self.view_model.add_task(self.task_input.text())
        if ok:
            self.task_input.clear()
            self.task_input.setFocus()

    def _on_remove_clicked(self) -> None:
        self.view_model.remove_task(self.todo_list.currentIndex().row())

    def _on_task_double_clicked(self, index: QModelIndex) -> None:
        self.view_model.toggle_task(index.row())

    def _on_selection_changed(self, current: QModelIndex) -> None:
        self.remove_button.setEnabled(current.isValid())


def main() -> int:
    app = QApplication(sys.argv)
    view_model = TodoListViewModel()
    window = MainWindow(view_model)
    window.show()
    return app.exec()


if __name__ == "__main__":
    raise SystemExit(main())

運行:

python app.py

十一、這個例子里的 MVVM 關系

可以用一張簡單的關系圖理解:

用戶點擊按鈕
    |
    v
View(MainWindow)
    |
    v
ViewModel(add_task / remove_task / toggle_task)
    |
    v
Model(TodoItem)
    |
    v
ViewModel 發(fā)出 message_changed / stats_changed 信號
    |
    v
View 更新 QLabel / QListView

關鍵點是:View 不直接處理業(yè)務。

比如添加任務時,View 只做:

ok = self.view_model.add_task(self.task_input.text())

至于:

  • 標題能不能為空。
  • 添加到哪里。
  • 統(tǒng)計信息怎么更新。
  • 錯誤信息怎么提示。

這些都放在 ViewModel 中。

十二、為什么不用 MainWindow 直接寫完

當然可以直接寫在 MainWindow 里:

def on_add_clicked(self):
    title = self.task_input.text().strip()
    if not title:
        self.message_label.setText("不能為空")
        return
    self.items.append(title)
    self.list_widget.addItem(title)

小工具沒問題。

但項目一旦變復雜,就會出現(xiàn)這些問題:

  1. 窗口類越來越長。
  2. 業(yè)務邏輯和界面邏輯混在一起。
  3. 很難寫單元測試。
  4. 多個窗口復用同一套邏輯很麻煩。
  5. UI 改版時容易誤傷業(yè)務邏輯。

MVVM 的價值不是讓代碼變少,而是讓代碼邊界更清楚。

十三、初學者常見誤區(qū)

誤區(qū) 1:ViewModel 里不能出現(xiàn)任何 Qt 類型

在 PyQt 項目里,ViewModel 繼承 QObject,使用 pyqtSignal 是很常見的做法。它確實依賴 Qt,但它不應該依賴具體窗口控件。

可以接受:

class UserViewModel(QObject):
    message_changed = pyqtSignal(str)

不建議:

class UserViewModel(QObject):
    def __init__(self, label: QLabel):
        self.label = label

前者是用 Qt 的通信機制,后者是直接操控界面控件。

誤區(qū) 2:用了 QStandardItemModel 就等于用了 MVVM

不是。

QStandardItemModel 是 Qt 的界面數(shù)據(jù)模型,主要服務于 QListViewQTableView、QTreeView

MVVM 的重點是:

  • 業(yè)務數(shù)據(jù)放在哪里。
  • 用戶命令放在哪里。
  • View 和業(yè)務邏輯是否解耦。
  • 狀態(tài)變化如何通知界面。

誤區(qū) 3:所有邏輯都要拆得很細

也不是。

如果只是一個 200 行的小工具,沒必要強行拆 10 個文件。可以先用單文件版本寫清楚:

  • Model 類。
  • ViewModel 類。
  • View 類。

等功能變多,再拆目錄。

十四、繼續(xù)擴展這個 demo

這個 demo 可以繼續(xù)擴展成更像真實項目的結構:

  1. 加入文件保存:把任務列表保存為 JSON。
  2. 加入數(shù)據(jù)庫:用 SQLite 保存任務。
  3. 加入搜索框:View 調用 ViewModel 的過濾方法。
  4. 加入任務優(yōu)先級:Model 增加 priority 字段。
  5. 加入多窗口:多個 View 共用同一個 ViewModel 或共享 Service。
  6. 加入單元測試:直接測試 ViewModel 的添加、刪除、統(tǒng)計邏輯。

例如,保存 JSON 時可以加一個 services/todo_repository.py

import json
from pathlib import Path

from models.todo_item import TodoItem


class TodoRepository:
    def __init__(self, path: str = "todos.json"):
        self.path = Path(path)

    def load(self) -> list[TodoItem]:
        if not self.path.exists():
            return []

        data = json.loads(self.path.read_text(encoding="utf-8"))
        return [TodoItem(**item) for item in data]

    def save(self, items: list[TodoItem]) -> None:
        data = [item.__dict__ for item in items]
        self.path.write_text(
            json.dumps(data, ensure_ascii=False, indent=2),
            encoding="utf-8",
        )

然后 ViewModel 依賴 Repository,而不是在 View 里讀寫文件。

十五、總結

使用 PyQt 開發(fā)桌面應用時,最容易犯的錯誤是把所有代碼都塞進窗口類。短期看寫得快,長期看維護成本會越來越高。

MVVM 的核心價值是分層:

  • Model:保存業(yè)務數(shù)據(jù)。
  • View:顯示界面,接收用戶操作。
  • ViewModel:處理界面命令、業(yè)務狀態(tài)和信號通知。

在 PyQt 中,可以使用:

  • QObject
  • pyqtSignal
  • QStandardItemModel
  • QListView
  • QMainWindow

來搭建一套簡單但清晰的 MVVM 架構。

對于 Python 開發(fā)者來說,剛開始不需要追求完美架構。建議先記住一句話:

讓窗口類少寫業(yè)務邏輯,讓 ViewModel 管狀態(tài)和命令。

只要做到這一點,你的 PyQt 項目就會比“所有代碼都寫在 MainWindow 里”更容易維護。

以上就是基于Python+PyQt+MVVM方式開發(fā)桌面應用的詳細內容,更多關于Python PyQt MVVM桌面應用的資料請關注腳本之家其它相關文章!

相關文章

  • 深入Python Tkinter 模塊

    深入Python Tkinter 模塊

    本文介紹Python Tkinter模塊,強調其輕量、跨平臺、無依賴的優(yōu)勢,適用于快速開發(fā)無需復雜環(huán)境配置的桌面工具,通過布局、事件回調、樣式美化等核心技巧,結合PyInstaller打包,實現(xiàn)從腳本到可交付程序的完整流程,適合制作簡單實用的小工具,感興趣的朋友跟隨小編一起看看吧
    2025-08-08
  • 使用python將csv數(shù)據(jù)導入mysql數(shù)據(jù)庫

    使用python將csv數(shù)據(jù)導入mysql數(shù)據(jù)庫

    這篇文章主要為大家詳細介紹了如何使用python將csv數(shù)據(jù)導入mysql數(shù)據(jù)庫,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-05-05
  • Python Pandas list列表數(shù)據(jù)列拆分成多行的方法實現(xiàn)

    Python Pandas list列表數(shù)據(jù)列拆分成多行的方法實現(xiàn)

    這篇文章主要介紹了Python Pandas list(列表)數(shù)據(jù)列拆分成多行的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • python使用opencv實現(xiàn)馬賽克效果示例

    python使用opencv實現(xiàn)馬賽克效果示例

    這篇文章主要介紹了python使用opencv實現(xiàn)馬賽克效果,結合實例形式分析了Python使用cv2模塊操作圖片實現(xiàn)馬賽克效果的相關技巧,需要的朋友可以參考下
    2019-09-09
  • TensorFlow-GPU完美安裝與配置的實現(xiàn)步驟

    TensorFlow-GPU完美安裝與配置的實現(xiàn)步驟

    本文主要介紹了TensorFlow-GPU的兩種安裝方法,推薦通過清華鏡像下載whl文件進行高效安裝,并提供版本升級、路徑查詢和環(huán)境配置步驟,感興趣的可以了解一下
    2026-04-04
  • Python數(shù)組與列表的區(qū)別解析

    Python數(shù)組與列表的區(qū)別解析

    列表因為其存儲的類型可以是任何對象,因此列表的用處更廣泛,更多樣化,并且列表可以有更多的存儲空間去使用,而數(shù)組使用的空間就相對較少,這篇文章主要介紹了Python數(shù)組與列表的區(qū)別,需要的朋友可以參考下
    2023-11-11
  • python中語法糖的妙用分享

    python中語法糖的妙用分享

    在Python中,語法糖是指一些為了增加代碼的可讀性、易用性和簡潔性而添加的特性,本文為大家整理了一些python中常見語法糖的使用,需要的小伙伴可以了解下
    2023-11-11
  • python?pdfplumber庫批量提取pdf表格數(shù)據(jù)轉換為excel

    python?pdfplumber庫批量提取pdf表格數(shù)據(jù)轉換為excel

    這篇文章主要為大家介紹了python使用pdfplumber庫批量提取pdf表格數(shù)據(jù)轉換為excel格式的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Python利用神經網絡解決非線性回歸問題實例詳解

    Python利用神經網絡解決非線性回歸問題實例詳解

    這篇文章主要介紹了Python利用神經網絡解決非線性回歸問題,結合實例形式詳細分析了Python使用神經網絡解決非線性回歸問題的相關原理與實現(xiàn)技巧,需要的朋友可以參考下
    2019-07-07
  • Django模板導入母版繼承和自定義返回Html片段過程解析

    Django模板導入母版繼承和自定義返回Html片段過程解析

    這篇文章主要介紹了Django模板導入母版繼承和自定義返回Html片段過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-09-09

最新評論

繁昌县| 台南市| 务川| 大洼县| 那曲县| 北碚区| 北辰区| 济源市| 正安县| 罗甸县| 陇南市| 泾源县| 伊吾县| 沅江市| 元阳县| 三明市| 蒙城县| 安丘市| 锡林郭勒盟| 桐城市| 清涧县| 碌曲县| 岗巴县| 女性| 尉犁县| 金门县| 青州市| 定西市| 平塘县| 尚义县| 德昌县| 丰城市| 蓬安县| 郎溪县| 景洪市| 本溪市| 合水县| 呼伦贝尔市| 铁岭市| 德安县| 海南省|