python3+PyQt5泛型委托详解

yipeiwu_com6年前Python基础

自定义委托可以让我们对视图中出现的数据项的外观和行为进行完全控制。如果有很多模型,可能会希望不是全部的大多数模型能够仅用一个自定义委托,如果不能这么做,那么对于这些自定义委托,将很有可能存在大量重复代码。为了使得维护工作变得轻松,更好的方法为不要为每个模型创建一个自定义委托,而是用一系列的通用组件来共同构成一个委托。本文通过Python3+pyqt5实现了python Qt GUI 快速编程的16章的泛型委托例子。

/home/yrd/eric_workspace/chap16/richtextlineedit.py

#!/usr/bin/env python3

import platform
import sys
import html
from PyQt5.QtCore import QSize, Qt,pyqtSignal
from PyQt5.QtGui import QColor, QFont,QFontMetrics, QIcon, QKeySequence, QPixmap,QTextCharFormat
from PyQt5.QtWidgets import QAction,QApplication,QMenu,QTextEdit


class RichTextLineEdit(QTextEdit):
 returnPressed=pyqtSignal()
 (Bold, Italic, Underline, StrikeOut, Monospaced, Sans, Serif,
  NoSuperOrSubscript, Subscript, Superscript) = range(10)


 def __init__(self, parent=None):
  super(RichTextLineEdit, self).__init__(parent)

  self.monofamily = "courier"
  self.sansfamily = "helvetica"
  self.seriffamily = "times"
  self.setLineWrapMode(QTextEdit.NoWrap)
  self.setTabChangesFocus(True)
  self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
  self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
  fm = QFontMetrics(self.font())
  h = int(fm.height() * (1.4 if platform.system() == "Windows"
         else 1.2))
  self.setMinimumHeight(h)
  self.setMaximumHeight(int(h * 1.2))
  self.setToolTip("Press <b>Ctrl+M</b> for the text effects "
    "menu and <b>Ctrl+K</b> for the color menu")


 def toggleItalic(self):
  self.setFontItalic(not self.fontItalic())


 def toggleUnderline(self):
  self.setFontUnderline(not self.fontUnderline())


 def toggleBold(self):
  self.setFontWeight(QFont.Normal
    if self.fontWeight() > QFont.Normal else QFont.Bold)


 def sizeHint(self):
  return QSize(self.document().idealWidth() + 5,
      self.maximumHeight())


 def minimumSizeHint(self):
  fm = QFontMetrics(self.font())
  return QSize(fm.width("WWWW"), self.minimumHeight())


 def contextMenuEvent(self, event):
  self.textEffectMenu()


 def keyPressEvent(self, event):
  if event.modifiers() & Qt.ControlModifier:
   handled = False
   if event.key() == Qt.Key_B:
    self.toggleBold()
    handled = True
   elif event.key() == Qt.Key_I:
    self.toggleItalic()
    handled = True
   elif event.key() == Qt.Key_K:
    self.colorMenu()
    handled = True
   elif event.key() == Qt.Key_M:
    self.textEffectMenu()
    handled = True
   elif event.key() == Qt.Key_U:
    self.toggleUnderline()
    handled = True
   if handled:
    event.accept()
    return
  if event.key() in (Qt.Key_Enter, Qt.Key_Return):
   self.returnPressed.emit()
   event.accept()
  else:
   QTextEdit.keyPressEvent(self, event)


 def colorMenu(self):
  pixmap = QPixmap(22, 22)
  menu = QMenu("Colour")
  for text, color in (
    ("&Black", Qt.black),
    ("B&lue", Qt.blue),
    ("Dark Bl&ue", Qt.darkBlue),
    ("&Cyan", Qt.cyan),
    ("Dar&k Cyan", Qt.darkCyan),
    ("&Green", Qt.green),
    ("Dark Gr&een", Qt.darkGreen),
    ("M&agenta", Qt.magenta),
    ("Dark Mage&nta", Qt.darkMagenta),
    ("&Red", Qt.red),
    ("&Dark Red", Qt.darkRed)):
   color = QColor(color)
   pixmap.fill(color)
   action = menu.addAction(QIcon(pixmap), text, self.setColor)
   action.setData(color)
  self.ensureCursorVisible()
  menu.exec_(self.viewport().mapToGlobal(
     self.cursorRect().center()))


 def setColor(self):
  action = self.sender()
  if action is not None and isinstance(action, QAction):
   color = QColor(action.data())
   if color.isValid():
    self.setTextColor(color)


 def textEffectMenu(self):
  format = self.currentCharFormat()
  menu = QMenu("Text Effect")
  for text, shortcut, data, checked in (
    ("&Bold", "Ctrl+B", RichTextLineEdit.Bold,
     self.fontWeight() > QFont.Normal),
    ("&Italic", "Ctrl+I", RichTextLineEdit.Italic,
     self.fontItalic()),
    ("Strike &out", None, RichTextLineEdit.StrikeOut,
     format.fontStrikeOut()),
    ("&Underline", "Ctrl+U", RichTextLineEdit.Underline,
     self.fontUnderline()),
    ("&Monospaced", None, RichTextLineEdit.Monospaced,
     format.fontFamily() == self.monofamily),
    ("&Serifed", None, RichTextLineEdit.Serif,
     format.fontFamily() == self.seriffamily),
    ("S&ans Serif", None, RichTextLineEdit.Sans,
     format.fontFamily() == self.sansfamily),
    ("&No super or subscript", None,
     RichTextLineEdit.NoSuperOrSubscript,
     format.verticalAlignment() ==
     QTextCharFormat.AlignNormal),
    ("Su&perscript", None, RichTextLineEdit.Superscript,
     format.verticalAlignment() ==
     QTextCharFormat.AlignSuperScript),
    ("Subs&cript", None, RichTextLineEdit.Subscript,
     format.verticalAlignment() ==
     QTextCharFormat.AlignSubScript)):
   action = menu.addAction(text, self.setTextEffect)
   if shortcut is not None:
    action.setShortcut(QKeySequence(shortcut))
   action.setData(data)
   action.setCheckable(True)
   action.setChecked(checked)
  self.ensureCursorVisible()
  menu.exec_(self.viewport().mapToGlobal(
     self.cursorRect().center()))


 def setTextEffect(self):
  action = self.sender()
  if action is not None and isinstance(action, QAction):
   what = action.data()
   if what == RichTextLineEdit.Bold:
    self.toggleBold()
    return
   if what == RichTextLineEdit.Italic:
    self.toggleItalic()
    return
   if what == RichTextLineEdit.Underline:
    self.toggleUnderline()
    return
   format = self.currentCharFormat()
   if what == RichTextLineEdit.Monospaced:
    format.setFontFamily(self.monofamily)
   elif what == RichTextLineEdit.Serif:
    format.setFontFamily(self.seriffamily)
   elif what == RichTextLineEdit.Sans:
    format.setFontFamily(self.sansfamily)
   if what == RichTextLineEdit.StrikeOut:
    format.setFontStrikeOut(not format.fontStrikeOut())
   if what == RichTextLineEdit.NoSuperOrSubscript:
    format.setVerticalAlignment(
      QTextCharFormat.AlignNormal)
   elif what == RichTextLineEdit.Superscript:
    format.setVerticalAlignment(
      QTextCharFormat.AlignSuperScript)
   elif what == RichTextLineEdit.Subscript:
    format.setVerticalAlignment(
      QTextCharFormat.AlignSubScript)
   self.mergeCurrentCharFormat(format)


 def toSimpleHtml(self):
  htmltext = ""
  black = QColor(Qt.black)
  block = self.document().begin()
  while block.isValid():
   iterator = block.begin()
   while iterator != block.end():
    fragment = iterator.fragment()
    if fragment.isValid():
     format = fragment.charFormat()
     family = format.fontFamily()
     color = format.foreground().color()     
     text=html.escape(fragment.text())
     if (format.verticalAlignment() ==
      QTextCharFormat.AlignSubScript):
      text = "<sub>{0}</sub>".format(text)
     elif (format.verticalAlignment() ==
       QTextCharFormat.AlignSuperScript):
      text = "<sup>{0}</sup>".format(text)
     if format.fontUnderline():
      text = "<u>{0}</u>".format(text)
     if format.fontItalic():
      text = "<i>{0}</i>".format(text)
     if format.fontWeight() > QFont.Normal:
      text = "<b>{0}</b>".format(text)
     if format.fontStrikeOut():
      text = "<s>{0}</s>".format(text)
     if color != black or family:
      attribs = ""
      if color != black:
       attribs += ' color="{0}"'.format(color.name())
      if family:
       attribs += ' face="{0}"'.format(family)
      text = "<font{0}>{1}</font>".format(attribs,text)
     htmltext += text
    iterator += 1
   block = block.next()
  return htmltext

if __name__ == "__main__":
 def printout(lineedit):
  print(str(lineedit.toHtml()))
  print(str(lineedit.toPlainText()))
  print(str(lineedit.toSimpleHtml()))    
 app = QApplication(sys.argv)
 lineedit = RichTextLineEdit()
 lineedit.returnPressed.connect(lambda:printout(lineedit))
 lineedit.show()
 lineedit.setWindowTitle("RichTextEdit")
 app.exec_()

/home/yrd/eric_workspace/chap16/genericdelegates.py

#!/usr/bin/env python3

from PyQt5.QtCore import (QDate, QSize, Qt)
from PyQt5.QtWidgets import (QApplication, QDateEdit, QLineEdit,
  QSpinBox, QStyledItemDelegate,QStyle)
from PyQt5.QtGui import QColor,QTextDocument
import richtextlineedit


class GenericDelegate(QStyledItemDelegate):

 def __init__(self, parent=None):
  super(GenericDelegate, self).__init__(parent)
  self.delegates = {}


 def insertColumnDelegate(self, column, delegate):
  delegate.setParent(self)
  self.delegates[column] = delegate


 def removeColumnDelegate(self, column):
  if column in self.delegates:
   del self.delegates[column]


 def paint(self, painter, option, index):
  delegate = self.delegates.get(index.column())
  if delegate is not None:
   delegate.paint(painter, option, index)
  else:
   QStyledItemDelegate.paint(self, painter, option, index)


 def createEditor(self, parent, option, index):
  delegate = self.delegates.get(index.column())
  if delegate is not None:
   return delegate.createEditor(parent, option, index)
  else:
   return QStyledItemDelegate.createEditor(self, parent, option,
             index)


 def setEditorData(self, editor, index):
  delegate = self.delegates.get(index.column())
  if delegate is not None:
   delegate.setEditorData(editor, index)
  else:
   QStyledItemDelegate.setEditorData(self, editor, index)


 def setModelData(self, editor, model, index):
  delegate = self.delegates.get(index.column())
  if delegate is not None:
   delegate.setModelData(editor, model, index)
  else:
   QStyledItemDelegate.setModelData(self, editor, model, index)


class IntegerColumnDelegate(QStyledItemDelegate):

 def __init__(self, minimum=0, maximum=100, parent=None):
  super(IntegerColumnDelegate, self).__init__(parent)
  self.minimum = minimum
  self.maximum = maximum


 def createEditor(self, parent, option, index):
  spinbox = QSpinBox(parent)
  spinbox.setRange(self.minimum, self.maximum)
  spinbox.setAlignment(Qt.AlignRight|Qt.AlignVCenter)
  return spinbox


 def setEditorData(self, editor, index):
  value = index.model().data(index, Qt.DisplayRole)
  editor.setValue(value)


 def setModelData(self, editor, model, index):
  editor.interpretText()
  model.setData(index, editor.value())


class DateColumnDelegate(QStyledItemDelegate):

 def __init__(self, minimum=QDate(),
     maximum=QDate.currentDate(),
     format="yyyy-MM-dd", parent=None):
  super(DateColumnDelegate, self).__init__(parent)
  self.minimum = minimum
  self.maximum = maximum
  self.format = format


 def createEditor(self, parent, option, index):
  dateedit = QDateEdit(parent)
  #dateedit=QDateTimeEdit(parent)
  dateedit.setDateRange(self.minimum, self.maximum)
  dateedit.setAlignment(Qt.AlignRight|Qt.AlignVCenter)
  dateedit.setDisplayFormat(self.format)
  dateedit.setCalendarPopup(True)
  return dateedit


 def setEditorData(self, editor, index):
  value = index.model().data(index, Qt.DisplayRole)
  #if value.isNull:
  editor.setDate(value)
  #editor.setDisplayFormat(self.format)

 def setModelData(self, editor, model, index):
  model.setData(index, editor.date())
 def paint(self, painter, option, index):
  text = index.model().data(index, Qt.DisplayRole).toString(self.format)
  palette = QApplication.palette()
  document = QTextDocument()
  document.setDefaultFont(option.font)
  if option.state & QStyle.State_Selected:
   document.setHtml("<font color={0}>{1}</font>".format(palette.highlightedText().color().name(),text))
  else:
   document.setHtml(text)
  painter.save()
  color = (palette.highlight().color()
     if option.state & QStyle.State_Selected
     else QColor(index.model().data(index,
        Qt.BackgroundColorRole)))
  painter.fillRect(option.rect, color)
  painter.translate(option.rect.x(), option.rect.y())
  document.drawContents(painter)
  painter.restore()  


class PlainTextColumnDelegate(QStyledItemDelegate):

 def __init__(self, parent=None):
  super(PlainTextColumnDelegate, self).__init__(parent)


 def createEditor(self, parent, option, index):
  lineedit = QLineEdit(parent)
  return lineedit


 def setEditorData(self, editor, index):
  value = index.model().data(index, Qt.DisplayRole)
  editor.setText(value)


 def setModelData(self, editor, model, index):
  model.setData(index, editor.text())


class RichTextColumnDelegate(QStyledItemDelegate):

 def __init__(self, parent=None):
  super(RichTextColumnDelegate, self).__init__(parent)


 def paint(self, painter, option, index):
  text = index.model().data(index, Qt.DisplayRole)
  palette = QApplication.palette()
  document = QTextDocument()
  document.setDefaultFont(option.font)
  if option.state & QStyle.State_Selected:
   document.setHtml("<font color={0}>{1}</font>".format(palette.highlightedText().color().name(),text))
  else:
   document.setHtml(text)
  painter.save()
  color = (palette.highlight().color()
     if option.state & QStyle.State_Selected
     else QColor(index.model().data(index,
        Qt.BackgroundColorRole)))
  painter.fillRect(option.rect, color)
  painter.translate(option.rect.x(), option.rect.y())
  document.drawContents(painter)
  painter.restore()


 def sizeHint(self, option, index):
  text = index.model().data(index).toString()
  document = QTextDocument()
  document.setDefaultFont(option.font)
  document.setHtml(text)
  return QSize(document.idealWidth() + 5,
      option.fontMetrics.height())


 def createEditor(self, parent, option, index):
  lineedit = richtextlineedit.RichTextLineEdit(parent)
  return lineedit


 def setEditorData(self, editor, index):
  value = index.model().data(index, Qt.DisplayRole)
  editor.setHtml(value)


 def setModelData(self, editor, model, index):
  model.setData(index, editor.toSimpleHtml())

/home/yrd/eric_workspace/chap16/carhirelog.pyw

#!/usr/bin/env python3

import bisect
import os
import platform
import sys
from PyQt5.QtCore import (QAbstractTableModel, QDate, QModelIndex,
  QVariant, Qt,pyqtSignal)
from PyQt5.QtWidgets import (QApplication, QMainWindow,
  QShortcut, QTableView)
from PyQt5.QtGui import QKeySequence
import genericdelegates


(LICENSE, CUSTOMER, HIRED, MILEAGEOUT, RETURNED, MILEAGEBACK,
 NOTES, MILEAGE, DAYS) = range(9)


class CarHireLog(object):

 def __init__(self, license, customer, hired, mileageout,
     returned=QDate(), mileageback=0, notes=""):
  self.license = license  # plain text
  self.customer = customer # plain text
  self.hired = hired     # QDate
  self.mileageout = mileageout   # int
  self.returned = returned    # QDate
  self.mileageback = mileageback  # int
  self.notes = notes   # HTML


 def field(self, column):
  if column == LICENSE:
   return self.license
  elif column == CUSTOMER:
   return self.customer
  elif column == HIRED:
   return self.hired
  elif column == MILEAGEOUT:
   return self.mileageout
  elif column == RETURNED:
   return self.returned
  elif column == MILEAGEBACK:
   return self.mileageback
  elif column == NOTES:
   return self.notes
  elif column == MILEAGE:
   return self.mileage()
  elif column == DAYS:
   return self.days()
  assert False


 def mileage(self):
  return (0 if self.mileageback == 0
     else self.mileageback - self.mileageout)


 def days(self):
  return (0 if not self.returned.isValid()
     else self.hired.daysTo(self.returned))


 def __hash__(self):
  return super(CarHireLog, self).__hash__()


 def __eq__(self, other):
  if self.hired != other.hired:
   return False
  if self.customer != other.customer:
   return False
  if self.license != other.license:
   return False
  return id(self) == id(other)


 def __lt__(self, other):
  if self.hired < other.hired:
   return True
  if self.customer < other.customer:
   return True
  if self.license < other.license:
   return True
  return id(self) < id(other)


class CarHireModel(QAbstractTableModel):
 dataChanged = pyqtSignal(QModelIndex,QModelIndex)
 def __init__(self, parent=None):
  super(CarHireModel, self).__init__(parent)
  self.logs = []

  # Generate fake data
  import gzip
  import random
  import string
  surname_data = gzip.open(os.path.join(
    os.path.dirname(__file__), "surnames.txt.gz")).read()
  surnames = surname_data.decode("utf8").splitlines()
  years = ("06 ", "56 ", "07 ", "57 ", "08 ", "58 ")
  titles = ("Ms ", "Mr ", "Ms ", "Mr ", "Ms ", "Mr ", "Dr ")
  notetexts = ("Returned <font color=red><b>damaged</b></font>",
    "Returned with <i>empty fuel tank</i>",
    "Customer <b>complained</b> about the <u>engine</u>",
    "Customer <b>complained</b> about the <u>gears</u>",
    "Customer <b>complained</b> about the <u>clutch</u>",
    "Returned <font color=darkred><b>dirty</b></font>",)
  today = QDate.currentDate()
  for i in range(250):
   license = []
   for c in range(5):
    license.append(random.choice(string.ascii_uppercase))
   license = ("".join(license[:2]) + random.choice(years) +
      "".join(license[2:]))
   customer = random.choice(titles) + random.choice(surnames)
   hired = today.addDays(-random.randint(0, 365))
   mileageout = random.randint(10000, 30000)
   notes = ""
   if random.random() >= 0.2:
    days = random.randint(1, 21)
    returned = hired.addDays(days)
    mileageback = (mileageout +
        (days * random.randint(30, 300)))
    if random.random() > 0.75:
     notes = random.choice(notetexts)
   else:
    returned = QDate()
    mileageback = 0
   log = CarHireLog(license, customer, hired, mileageout,
        returned, mileageback, notes)
   bisect.insort(self.logs, log)


 def rowCount(self, index=QModelIndex()):
  return len(self.logs)


 def columnCount(self, index=QModelIndex()):
  return 9


 def data(self, index, role):
  if not index.isValid():
   return QVariant()
  if role == Qt.DisplayRole:
   log = self.logs[index.row()]
   value = log.field(index.column())
   if (index.column() in (MILEAGEBACK, MILEAGE, DAYS) and
    value == 0):
    return 0
   return value
  if (role == Qt.TextAlignmentRole and
   index.column() not in (LICENSE, CUSTOMER, NOTES)):
   return QVariant(int(Qt.AlignRight|Qt.AlignVCenter))
  if role == Qt.BackgroundColorRole:
   palette = QApplication.palette()
   if index.column() in (LICENSE, MILEAGE, DAYS):
    return QVariant(palette.alternateBase())
   else:
    return QVariant(palette.base())
  return QVariant()


 def setData(self, index, value, role=Qt.EditRole):
  if (index.isValid() and role == Qt.EditRole and
   index.column() not in (LICENSE, MILEAGE, DAYS)):
   log = self.logs[index.row()]
   column = index.column()
   if column == CUSTOMER:
    log.customer = value
   elif column == HIRED:
    #log.hired = value.toDate()
    log.hired = value
   elif column == MILEAGEOUT:
    log.mileageout = value
   elif column == RETURNED:
    #log.returned = value.toDate()
    log.returned = value
   elif column == MILEAGEBACK:
    log.mileageback = value
   elif column == NOTES:
    log.notes = value
   self.dataChanged[QModelIndex,QModelIndex].emit(index,index)
   return True
  return False


 def headerData(self, section, orientation, role):
  if role == Qt.TextAlignmentRole:
   if orientation == Qt.Horizontal:
    return QVariant(int(Qt.AlignCenter))
   return QVariant(int(Qt.AlignRight|Qt.AlignVCenter))
  if role != Qt.DisplayRole:
   return QVariant()
  if orientation == Qt.Horizontal:
   if section == LICENSE:
    return "License"
   elif section == CUSTOMER:
    return "Customer"
   elif section == HIRED:
    return "Hired"
   elif section == MILEAGEOUT:
    return "Mileage #1"
   elif section == RETURNED:
    return "Returned"
   elif section == MILEAGEBACK:
    return "Mileage #2"
   elif section == DAYS:
    return "Days"
   elif section == MILEAGE:
    return "Miles"
   elif section == NOTES:
    return "Notes"
  return section + 1


 def flags(self, index):
  flag = QAbstractTableModel.flags(self, index)
  if index.column() not in (LICENSE, MILEAGE, DAYS):
   flag |= Qt.ItemIsEditable
  return flag


class HireDateColumnDelegate(genericdelegates.DateColumnDelegate):

 def createEditor(self, parent, option, index):
  i = index.sibling(index.row(), RETURNED)
  self.maximum = i.model().data(i, Qt.DisplayRole).addDays(-1)
  return genericdelegates.DateColumnDelegate.createEditor(
    self, parent, option, index)


class ReturnDateColumnDelegate(genericdelegates.DateColumnDelegate):

 def createEditor(self, parent, option, index):
  i = index.sibling(index.row(), HIRED)
  self.minimum = i.model().data(i, Qt.DisplayRole).addDays(1)
  return genericdelegates.DateColumnDelegate.createEditor(
    self, parent, option, index)


class MileageOutColumnDelegate(genericdelegates.IntegerColumnDelegate):

 def createEditor(self, parent, option, index):
  i = index.sibling(index.row(), MILEAGEBACK)
  maximum = i.model().data(i, Qt.DisplayRole)
  self.maximum = 1000000 if maximum == 0 else maximum - 1
  return genericdelegates.IntegerColumnDelegate.createEditor(
    self, parent, option, index)


class MileageBackColumnDelegate(genericdelegates.IntegerColumnDelegate):

 def createEditor(self, parent, option, index):
  i = index.sibling(index.row(), MILEAGEOUT)
  self.minimum = i.model().data(i, Qt.DisplayRole) + 1
  return genericdelegates.IntegerColumnDelegate.createEditor(
    self, parent, option, index)


class MainForm(QMainWindow):

 def __init__(self, parent=None):
  super(MainForm, self).__init__(parent)

  model = CarHireModel(self)

  self.view = QTableView()
  self.view.setModel(model)
  self.view.resizeColumnsToContents()

  delegate = genericdelegates.GenericDelegate(self)
  delegate.insertColumnDelegate(CUSTOMER,
    genericdelegates.PlainTextColumnDelegate())
  earliest = QDate.currentDate().addYears(-3)
  delegate.insertColumnDelegate(HIRED,
    HireDateColumnDelegate(earliest))
  delegate.insertColumnDelegate(MILEAGEOUT,
    MileageOutColumnDelegate(0, 1000000))
  delegate.insertColumnDelegate(RETURNED,
    ReturnDateColumnDelegate(earliest))
  delegate.insertColumnDelegate(MILEAGEBACK,
    MileageBackColumnDelegate(0, 1000000))
  delegate.insertColumnDelegate(NOTES,
    genericdelegates.RichTextColumnDelegate())

  self.view.setItemDelegate(delegate)
  self.setCentralWidget(self.view)

  QShortcut(QKeySequence("Escape"), self, self.close)
  QShortcut(QKeySequence("Ctrl+Q"), self, self.close)

  self.setWindowTitle("Car Hire Logs")


app = QApplication(sys.argv)
form = MainForm()
rect = QApplication.desktop().availableGeometry()
form.resize(int(rect.width() * 0.7), int(rect.height() * 0.8))
form.move(0, 0)
form.show()
app.exec_()

运行结果:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持【听图阁-专注于Python设计】。

相关文章

基于python使用tibco ems代码实例

 这篇文章主要介绍了基于python使用tibco ems代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 TIBCO...

Python3.2模拟实现webqq登录

这是我最初学习时自己做的一个python模拟登录webqq的实例代码,具体代码如下 import hashlib from urllib import request,parse f...

Python中asyncio与aiohttp入门教程

Python中asyncio与aiohttp入门教程

很多朋友对异步编程都处于“听说很强大”的认知状态。鲜有在生产项目中使用它。而使用它的同学,则大多数都停留在知道如何使用 Tornado、Twisted、Gevent 这类异步框架上,出现...

python实现类之间的方法互相调用

all.py from son import * class ALL(): def __init__(self): self.mSon = SON(self) def get...

python中的不可变数据类型与可变数据类型详解

前言 python与C/C++不一样,它的变量使用有自己的特点,当初学python的时候,一定要记住“一切皆为对象,一切皆为对象的引用”这句话,其实这个特点类似于JAVA,所以在pyth...