整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          「每日一學」Python中的運算符重載

          ython中的運算符重載是指根據對象的不同類型,改變運算符的行為。運算符重載可以讓自定義對象支持內置的運算符,如加法、比較、索引等。Python中的運算符重載非常方便,只需要在類中定義并實現一個與運算符對應的特殊方法。例如:

          # 定義一個向量類
          class Vector:
              def __init__(self, x, y):
                  self.x = x
                  self.y = y
          
              # 重載加法運算符
              def __add__(self, other):
                  return Vector(self.x + other.x, self.y + other.y)
          
              # 重載等于運算符
              def __eq__(self, other):
                  return self.x == other.x and self.y == other.y
          
          # 創建兩個向量對象
          v1 = Vector(1, 2)
          v2 = Vector(3, 4)
          
          # 使用加法運算符
          v3 = v1 + v2
          print(v3.x, v3.y) # 4 6
          
          # 使用等于運算符
          print(v1 == v2) # False
          

          Python中可以重載的運算符有很多,不同的運算符對應不同的特殊方法,如下表所示:

          運算符

          特殊方法

          +

          add

          -

          sub

          *

          mul

          /

          truediv

          //

          floordiv

          %

          mod

          **

          pow

          <

          lt

          <=

          le

          >

          gt

          >=

          ge

          ==

          eq

          !=

          ne

          []

          getitem

          ()

          call

          Python中,可以通過定義特殊方法來重載操作符。

          例如: 要重載+ (加法運算符),定義__add__:

          class Vector:
              def __init__(self, x, y):
                  self.x = x
                  self.y = y
                  
              def __add__(self, other):
                  return Vector(self.x + other.x, self.y + other.y)
          
          v1 = Vector(1, 2)  
          v2 = Vector(2, 3)  
          v3 = v1 + v2   # 調用Vector.__add__(v1, v2)
          print(v3.x, v3.y)  # 3 5
          

          - 要重載- (減法運算符),定義__sub__:

          def __sub__(self, other):
              return Vector(self.x - other.x, self.y - other.y)
          
          v3 = v1 - v2    
          print(v3.x, v3.y)  # -1 -1

          - 要重載* (乘法運算符),定義__mul__:

          def __mul__(self, scalar):
              return Vector(self.x * scalar, self.y * scalar)  
          
          v4 = v1 * 3
          print(v4.x, v4.y)  # 3 6
          

          - 要重載/ (除法運算符),定義__truediv__:

          def __truediv__(self, scalar):
              return Vector(self.x / scalar, self.y / scalar) 
          
          v4 = v1 / 2  
          print(v4.x, v4.y)  # 0.5 1
          

          - 要重載[] (下標訪問),定義__getitem__:

          def __getitem__(self, index):
              if index == 0:
                  return self.x
              elif index == 1:
                  return self.y
              else:
                  raise IndexError  
          
          print(v1[0])  # 1  
          print(v1[1])  # 2
          

          - 可以重載Python中的任何操作符,只需要定義相應的特殊方法。其他示例還包括:

          1. __len__ 用于 len()
          2. __eq__ 用于 == (等號)
          3. __ne__ 用于 != (不等于)
          4. __gt__ 用于 > (大于)
          5. __lt__ 用于 < (小于)
          6. __le__ 用于 <= (小于等于)
          7. __ge__ 用于 >= (大于等于)

          何用標準化的,通用的純函數編程語言Haskell來構建Web?Haskell構建的Web擁有著什么樣的優點呢?讓我們來看看構建的過程吧。

          作者 | William Yao

          譯者 |彎月,責編 | maozz

          出品 | CSDN(ID:CSDNnews)

          以下為譯文:

          Haskell有大量的庫可用于滿足基本的后臺需求,從日志輸出到數據庫訪問,再到Web服務器的定義和路由,應有盡有。

          擁有選擇的自由固然很好,但如果你剛剛接觸這個領域,那么大量的選擇可能會讓你目不暇接。也許你沒法自信地判斷出這些選擇之間的區別。例如,你需要查詢數據庫。

          那么,你需要Squeal提供的列名強保證,以及深度SQL嵌入功能嗎?還是青睞Opaleye在保證類型安全的前提下的簡單性?或者只是使用簡單的postgresql-simple就好?還是使用Selda?或者……

          我用最簡單的庫寫了一個Web應用程序,一方面是想告訴你,你不需要擔心技術棧是否足夠先進,另一方面也是我自己的學習過程。

          如果你不知道怎樣用Haskell構建真正的應用程序,為什么不去學習呢?我會盡可能保持代碼的簡單性。

          點擊此處可查看源代碼(https://gitlab.com/williamyaoh/haskell-web-stack)。

          下面我們來看一看我選擇的這些庫,以及它們的功能,還有這個應用程序的功能。

          這個Web應用程序究竟是什么呢?

          它是一個網站,用戶可以在這個網站上創建定時器和做筆記。

          我舉個例子說明該網站的用途:某人想設置多個定時器來跟蹤多個反應物的過程,同時用筆記來記錄他們需要關心的事情、下次制作配方時需要改進的事情,等等。

          再舉一個例子,某個人在玩MOBA游戲,比如英雄聯盟或者刀塔2,他們可以在另一臺顯示器上打開一個頁面來跟蹤關鍵技能的冷卻時間,同時用筆記記錄宏操作、對手的組合,以及團戰時需要關注技的冷卻等。

          在這個應用程序中我將演示:

          • 會話,用戶可以刷新頁面,或者關閉頁面后再打開,但在打開之后應該看到相同的內容。

          • 持久化和數據庫訪問,我們需要將每個用戶的定時器和筆記保存下來。另一個需求是定時器需要維持剩余的時間(用戶設置了一個30分鐘的定時器,然后不小心關閉了頁面,應該如何?)

          • 運行時的配置,因為我們不能把數據庫連接的信息硬編碼到代碼里。

          • 日志。日志對于Web應用的作用不言而喻。

          我用到了哪些庫?

          路由和Web服務器:Spock

          最終我選擇了Spock,因為它易于使用。如果你用過Ruby的Sinatra,那么Spock應該不會陌生。Spock也自帶了會話管理,這一點非常好。

          例如,定義一個擁有幾條路由的服務器,返回HTML和JSON,代碼大致如下:

          {-# LANGUAGE OverloadedStrings #-}

          import Web.Spock as Spock

          import Web.Spock.Config as Spock

          import Data.Aeson as A

          main :: IO

          main = do

          spockCfg <- defaultSpockCfg PCNoDatabase

          runSpock 3000 $ spock spockCfg $ do

          get root $ do

          Spock.html "<div>Hello world!</div>"

          get "users" $ do

          Spock.json (A.object [ "users" .= users ])

          get ("users" <//> var <//> "friends") $ \userID -> do

          Spock.json (A.object [ "userID" .= (userID :: Int), "friends" .= A. ])

          where users :: [String]

          users = ["bob", "alice"]

          數據庫訪問:postgresql-simple

          postgresql-simple基本上只允許您對數據庫運行原始SQL查詢,而沒有多余的裝飾,例如防止注入攻擊。它可以實現您的期望,僅此而已。

          {-# LANGUAGE OverloadedStrings #-}

          import Database.PostgreSQL.Simple

          userLoginsQuery :: Query

          userLoginsQuery =

          "SELECT l.user_id, COUNT(1) FROM logins l GROUP BY l.user_id;"

          getUserLogins :: Connection -> IO [(Int, Int)]

          getUserLogins conn = query_ conn userLoginsQuery

          數據庫訪問:postgresql-simple

          postgresql-simple可以讓你在數據庫上運行原始的SQL查詢,它只提供最基本的額外處理,比如防止注入攻擊等。它僅完成你需要的東西,沒有任何額外的功能。

          {-# LANGUAGE OverloadedStrings #-}

          import Database.PostgreSQL.Simple

          userLoginsQuery :: Query

          userLoginsQuery =

          "SELECT l.user_id, COUNT(1) FROM logins l GROUP BY l.user_id;"

          getUserLogins :: Connection -> IO [(Int, Int)]

          getUserLogins conn = query_ conn userLoginsQuery

          配置:configurator

          configurator能夠從文件中讀取配置,并解析成Haskell數據類型。與普通的配置文件讀取器相比它的功能要多一些。

          如果你習慣了直接讀取配置文件,那么configurator還有一些額外功能。例如,配置項可以嵌套分組,configurator還提供了熱重載來監視配置文件變化。

          # An example config file.

          app_name = "The Whispering Fog"

          db {

          pool {

          stripes = 4

          resource_ttl = 300

          }

          username = "pallas"

          password = "thefalloflatinium"

          dbname = "italy"

          }

          {-# LANGUAGE OverloadedStrings #-}

          import Data.Configurator as Cfg

          import Database.PostgreSQL.Simple

          data MyAppConfig = MyAppConfig

          { appName :: String

          , appDBConnection :: Connection

          }

          getAppConfig :: IO MyAppConfig

          getAppConfig = do

          cfgFile <- Cfg.load ["app-configuration.cfg"]

          name <- Cfg.require cfgFile "app_name"

          conn <- do

          username <- Cfg.require cfgFile "db.username"

          password <- Cfg.require cfgFile "db.password"

          dbname <- Cfg.require cfgFile "db.dbname"

          connect $ defaultConnectInfo

          { connectUser = username

          , connectPassword = password

          , connectDatabase = dbname

          }

          pure $ MyAppConfig

          { appName = name

          , appDBConnection = conn

          }

          日志:fast-logger

          fast-logger提供了一個相對簡單易用的日志解決方案。在Web應用程序的示例中,我只輸出到了stderr,但它還可以支持輸出日志到文件。雖然它支持許多類型,但絕大多數情況下,你需要定義一個輔助函數,接收一個LoggerSet,以及需要記錄的信息。

          import System.Log.FastLogger as Log

          logMsg :: Log.LoggerSet -> String -> IO

          logMsg logSet msg =

          Log.pushLogStrLn logSet (Log.toLogStr msg)

          doSomething :: IO

          doSomething = do

          logSet <- Log.newStderrLoggerSet Log.defaultBufSize

          logMsg logSet "message 1"

          logMsg logSet "message 2"

          HTML生成:blaze-html

          盡管本項目的后臺并不需要生成太多HTML,但值得一提的是,blaze-html正是我需要的。

          基本上它就是將HTML淺層嵌入到了Haskell DSL中。如果你會編寫HTML,那你就會使用這個庫。

          {-# LANGUAGE OverloadedStrings #-}

          import Data.ByteString.Lazy

          import Text.Blaze.Html5 as HTML

          import Text.Blaze.Html5.Attributes as HTML hiding ( title )

          import Text.Blaze.Html.Renderer.Utf8 as HTML

          dashboardHTML :: HTML.Html

          dashboardHTML = HTML.html $

          HTML.docTypeHtml $ do

          HTML.head $ do

          HTML.title "Timers and Notes"

          HTML.meta ! HTML.charset "utf-8"

          HTML.script ! HTML.src "/js/bundle.js" $ ""

          HTML.body $ do

          HTML.div ! HTML.id "content" $ ""

          dashboardBytes :: ByteString

          dashboardBytes = HTML.renderHtml dashboardHTML

          構建前端:make + npm

          沒錯,它們并不是庫。但我們依然需要某種JavaScript前端,因為定時器需要實時更新。Webpack能夠生成JS包,而Make能夠組裝最終的應用程序。

          這些東西無需我多說,網上有很多相關的資源。

          我必須要用這些庫嗎?

          當然不是。如果你第一次接觸Haskell,那么有這些疑問是很自然的。不要讓這篇文章限制了你的思路。盡管這個應用程序可以運行,但許多部分用于生產環境下的Haskell時并不理想。

          例如,許多Haskell程序員很可能會使用Servant而不是Spock來定義API端點。如果你想了解其他庫,那當然應該跟隨你的直覺。

          你可以把這些庫和這個應用程序作為起點。我建議你用這些代碼作為學習的機會,理解它的原理,然后自己試著修改。Haskell很好的一點就是它非常易于重構或者升級,而不會破壞已有的功能。

          一旦掌握了這個應用程序,就可以用更高級的庫來替換它們,來獲得更多的保證。同時,這也是一個增量學習的過程。

          將數據庫訪問的庫從postgresql-simple升級到支持類型安全的庫。我推薦Opaleye!

          將API定義的庫從Spock升級到Servant

          利用QuickCheck或hedgehog增加自動測試。例如,你可以測試服務器的每個錯誤響應都返回了JSON格式的錯誤信息。

          你還可以嘗試替換前端和構建系統。

          升級前端,使用PureScript或Elm來替換原始的JavaScript

          升級構建系統,利用Shake替換make構建更健壯的系統

          原文:https://williamyaoh.com/posts/2019-11-16-a-dead-simple-web-stack.html

          本文為 CSDN 翻譯,轉載請注明來源出處。

          【End】


          主站蜘蛛池模板: 蜜桃视频一区二区| 国产精品区一区二区三在线播放 | 无码一区二区三区视频| 一区二区三区高清| 国产一区二区不卡在线播放| 午夜在线视频一区二区三区| 人妻体内射精一区二区三区| 激情内射亚州一区二区三区爱妻| 国产精品无码一区二区三区毛片| 美女啪啪一区二区三区| 国产伦一区二区三区高清 | 波多野结衣免费一区视频| 日韩三级一区二区三区| 精品欧洲av无码一区二区14| 亚洲中文字幕无码一区| 色视频综合无码一区二区三区 | 亚洲av无码一区二区三区不卡 | 手机看片一区二区| 国产乱码精品一区二区三| 男人的天堂精品国产一区| 日本高清一区二区三区| 免费播放一区二区三区| 亚洲狠狠久久综合一区77777 | 国产成人久久一区二区三区| 在线精品视频一区二区| 精品一区精品二区制服| 亚洲福利一区二区三区| 97av麻豆蜜桃一区二区| 免费无码VA一区二区三区| 亚洲国产日韩在线一区| 亚洲Av高清一区二区三区| 国产福利微拍精品一区二区| 日韩一区二区在线播放| 国产一区二区在线| 在线日韩麻豆一区| 久久精品国产一区二区| 国产在线精品一区二区中文 | 99精品国产高清一区二区麻豆| 日产精品久久久一区二区| 少妇激情av一区二区| 亚洲av乱码一区二区三区|