Django 手動 seed 資料

Published on:

獨立的程式碼要對Django Model 進行讀寫一般都是吃錯吃爽爽

這裡記錄一下怎麼解決 測試版本 Django 2.2.11

X 代表 我的 Django Project 名稱

import sys,os

'''
導入Django Project 路徑,我習慣將 app 都放進 apps,並且這個 seed.py 我會跟著我的app 跑
因此我使用 os.path.abspath("../..") 回到 Django Project 的根目錄即可
'''
# sys.path.append(os.path.join(os.path.dirname(__file__), 'X'))  

sys.path.append(os.path.abspath("../.."))

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "X.settings")
from django.conf import settings
from django.core.wsgi import get_wsgi_application

application = get_wsgi_application()

'''
底下就可以操作資料庫了
'''
from proc.models import Station
Station.objects.create(name="Apple",code="A").save()

MySQL Ver 14.14 相關設定

Published on:

解決ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

set global validate_password_policy=0;
set global validate_password_length=1;

validate_password_policy 取值
0 or LOW 只驗證長度
1 or MEDIUM 驗證長度、數字、大小寫、特殊字符
2 or STRONG 驗證長度、數字、大小寫、特殊字符、字典文件



新版的 mysql root 不能直接使用,使用要建立一個新的使用者並且給予權限
CREATE USER 'user'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON . TO 'user'@'localhost' IDENTIFIED BY 'password'; //MySQL
GRANT ALL PRIVILEGES ON . TO 'myaccount'@'localhost' WITH GRANT OPTION; //MariaDB
FLUSH PRIVILEGES;

Vue + element 【environment debug】

Published on:

Vue (3.8.4) + Element (2.0)

官方文件的錯誤

.babelrc 原始修改:

{
  "presets": [["es2015", { "modules": false }]],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

一開始會出現: 找不到 babel-preset-es2015 的錯誤,Google之後大多是叫你安裝
npm install --save babel-preset-es2015
但是之後就會吃
Error: Plugin/Preset files are not allowed to export objects, only functions. In E:vue3-confignode_modulesbabel-preset-es2015libindex.js 這個錯誤

結論:

  1. 其實要安裝 @babel/preset-env npm i @babel/preset-env -D
  2. 修改 .babelrc 把官方文件的 es2015 -> @babel/preset-env
    {
      "presets": [["@babel/preset-env", { "modules": false }]],
      "plugins": [
          [
            "component",
            {
              "libraryName": "element-ui",
              "styleLibraryName": "theme-chalk"
            }
          ]
      ]
    }
    

ERR: not found !!vue-style-loader!css-loader?{"sourceMap":true}!

This dependency was not found:

* !!vue-style-loader!css-loader?{"sourceMap":true}!../../node_modules/vue-loader/lib/style-compiler/index?{"vue":true,"id":"data-v-08b35dbd","scoped":true,"hasInlineC
onfig":false}!sass-loader?{"sourceMap":true}!../../node_modules/vue-loader/lib/selector?type=styles&index=0!./MainUI.vue in ./src/components/MainUI.vue

To install it, you can run: npm install --save !!vue-style-loader!css-loader?{"sourceMap":true}!../../node_modules/vue-loader/lib/style-compiler/index?{"vue":true,"id
":"data-v-08b35dbd","scoped":true,"hasInlineConfig":false}!sass-loader?{"sourceMap":true}!../../node_modules/vue-loader/lib/selector?type=styles&index=0!./MainUI.vue

解決方法

npm install node-sass sass-loader --save-dev;

Django 筆記 1

Published on:

Reference: Django Girls 教學指南

Django 介紹

Django (/ˈdʒæŋɡoʊ/ jang-goh) , Python 最有名的 Web Framework。
例如如 Pinterest, Instagram, Disqus 等等都使用過它來開發。

什麼是Web Framework?

  1. 一個既定的骨架,必須按照它的規範寫程式,這對於目標程式的開發速度、再利用性、和程式可讀性等等都有相當大的好處。
  2. 強大且豐富的函式庫 ( Libraries ),使用者認證、安全機制、URL mapping、資料庫連接等..,都可以直接使用並且專注在客製化功能。

它有以下的特色:

  1. 免費開放原始碼 (Free)
  2. 著重快速開發、高效能
  3. 淺顯易懂和優雅的程式碼,並遵從 DRY ( Don't Repeat Yourself ) 守則
  4. 使用 Model–View–Templates (MVT)的架構

運作流程解釋

使用者瀏覽器 => Route(URL Conf) => View => Model(如果需要從資料庫取出資料,否則跳過) => Template(輸出成Html) => 使用者瀏覽器

如何安裝?

pip install django

建立第一個專案 (我的專案名稱叫 mysite)

django-admin startproject mysite
如果建立成功就可以看到有一個資料夾出現,裡面的結構如下

mysite
├── manage.py
└── mysite
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

建立第一個APP (hello)

django-admin startapp hello
每一個App的結構都是相同的

hello/
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│   └── __init__.py
├── models.py
├── tests.py
└── views.py

將app 註冊到Django

編輯 mysite\mysite\settings.py,加入hello 到INSTALLED_APP

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'hello',
)

替第一個App建立路由

編輯 mysite\mysite\urls.py,加入路由,由於我們第一個App叫hello,所以我希望網址長這樣http://127.0.0.1/hello
所以我在urls 裡面加入 hello

from django.contrib import admin
from django.urls import path
from hello import views as hello_views  # new

  
urlpatterns = [
    path('hello/', hello_views),  # new

    path('admin/', admin.site.urls),
]

建立第一個View (function 版本)

由於我們在上面已經寫了 from hello import views as hello_views,所以我們接下來要建立views
編輯 mysite\hello\views,加入

from django.http import HttpResponse
 
def index(request):
    return HttpResponse("Hello Django")

建立基本資料庫

D:\mysite\>python manage.py migrate

使用開發服務

D:\mysite\>python manage.py runserver
預設是127.0.0.1,port 都是 8000, 都可以自己替換,指令如下 (127.0.0.1, localhost 都是指向本機的位置, 0.0.0.0 表示可以接受任何的位置連線)
python manage.py runserver 0.0.0.0:8888


python manage.py runserver
Performing system checks...
....
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Python 筆記 6

Published on:

裝飾器 物件版 - 不帶參數

Python 會將被修飾的 function 傳入 init,另外再直接覆寫 call ,然後在呼叫 self.f 的前後作額外的修飾動作。

class A(object):
    def __init__(self, f):
        self.f = f
    
    def __call__(self, *args, **kargs):
        print("A before call")
        result = self.f(*args, **kargs)
        print("A after call")
        return result


@A
def run_my_function():
    print("run_my_function.")

run_my_function()
A before call
hello run_my_function.
A after call

裝飾器 物件版 - 參數

帶參數的版本會傳入 decorator 的參數,function 本體則是會在 call中被傳入,這是不一樣的地方。

class B(object):
    def __init__(self, name, powerLevel):
        self.name = name
        self.powerLevel = powerLevel

    def __call__(self, f):
        def d_f(*args, **kargs):
            print("%s %s before call" % (self.powerLevel, self.name))
            result = f(*args, **kargs)
            print("%s %s after call" % (self.powerLevel, self.name))
            return result
        return d_f

@B('Death Knight', '80% rot')
def power_set_80():
    print("Attack! power 80%")

@B('Gandalf', '30% rot')
def power_set_30():
    print("Attack! power 30%")

power_set_80()
print('')
power_set_30()
80% rot Death Knight before call
Attack! power 80%
80% rot Death Knight after call

30% rot Gandalf before call
Attack! power 30%
30% rot Gandalf after call

Assert 用法

使用assert在出現錯誤條件時就崩潰,可以產生很多便利的控制,如果表達式為false,Python會引發一個AssertionError異常。
assert Expression[, Arguments]

assert False, "帥,我崩潰了!"
---------------------------------------------------------------------------

AssertionError                            Traceback (most recent call last)

<ipython-input-6-fc775a992d47> in <module>()
----> 1 assert False, "帥,我崩潰了!"


AssertionError: 帥,我崩潰了!

靜態方法 和 物件方法

一般使用物件的方法必須要實體化一個物件再使用該物件的方法。

@staticmethod 或 @classmethod 就可以不需要實體化就直接呼叫
靜態方法 (@staticmethod) 是真的 static 所以就不需要 self 參數
物件方法 (@classmethod) 是在一般和靜態中間的方法,需要自身的cls 參數

class A(object):
  go_status = 1
  def go(self):
    print('gogo')

  @staticmethod
  def static_go():
    print('static go')
    print(A.go_status)

  @classmethod
  def class_go(cls):
    print('class go')
    print(cls.go_status)
    cls().go()

A.static_go()
A.class_go()
static go
1
class go
1
gogo

Django ctypes 無法正常退出的問題

Published on:

Django Autoreload

從我開始接觸Django時,runserver 就已經有autoreload了,由於其他Framework都有其實是很平常的了...
最近有些實務上會用到ctypes但是又造成restart, autoreload會卡住,使得要手動停止進程,在這邊記錄一下
先研究Auto Reload的方法
從runserver.py 找到 autoreload.main ,會call autoreload.py

1. runserver.py(run  inner_run before  fork a  child process A).
2. child process A new  a thread B.
3. parent process wait child process the end.
4. child process scan all module by sec , if code change return exit 3.
5. Thread B running inner_run.
6. parent process get return exit code is 3, refork agian then jump to step 2.

django/utils/autoreload.py 的280 行sys.ext(3) 前面加入自己處理的function 就可以了

問題還是沒解決,手動stop的時候還是會卡住........ Orz

django/core/management/base.py 的 class BaseCommand 的 run_from_argv function 可以找到connections.close_all()
約在297行,會呼叫connections.close_all() , I got you!
這樣一來不管是reload 還是stop 都可以自己解決了!

我自己問題的解法...

django/__init__.py 最底下加入

def close_custom():
    from MES.mes_core import MESCore
    me = MESCore()
    try:
        me.mes_stop()
    except Exception as e:
        print(e)

django/core/management/base.py 297行插入 close_custom()

  ...
  try:
    close_custom()
    connections.close_all()
  except ImproperlyConfigured:
    pass
    #Ignore if connections aren't setup at this point (e.g. no configured settings).

    
    ...

Python 筆記 5

Published on:

Python 物件 初入江湖的講解

當Python建立物件的流程
1. 呼叫new()建立物件。
《一般我們不會特別建立new()方法,所以Python會去找基礎類別裡的new() 【object.new()】》
2. 呼叫init()進行物件初始化。

在Python中,function 方法的第一個參數是指向物件本身的參照,習慣命名用 "self"

class BMI:
    def __init__(self,h=0,w=0):
        self.height=h
        self.weight=w
    def calculate_bmi(self):
        return self.weight / ((self.height/100)**2)

bmi = BMI(180,80)
bmi.calculate_bmi()

24.691358024691358

物件 private method

Python的類別所有的方法預設都是public,在別的程式語言會有public、protected、private之類的method修飾詞來設定。
Python是使用2個底線

class ClassB(object):
  def __private_method(self):
    print("this is for personal only")

  def get_private_method(self):
    self.__private_method()

b = ClassB()

b.get_private_method()
b.__private_method()

this is for personal only



---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-6-ddd1f6413632> in <module>()
      9 
     10 b.get_private_method()
---> 11 b.__private_method()


AttributeError: 'ClassB' object has no attribute '__private_method'

物件 繼承

繼承就是為了避免多個類別間重複定義相同的行為
底下是沒有繼承是舉例

class SwordsMan():
    def __init__(self,名稱,等級,血量):
        self.角色名稱 = 名稱
        self.角色等級 = 等級
        self.角色血量 = 血量
        
    def 戰鬥(self):
        print("揮劍攻擊")
        
    def __str__(self):
        return '({名稱},{等級},{血量})'.format(名稱=self.角色名稱,等級=self.角色等級,血量=self.角色血量)
    
class Magician():
    def __init__(self,名稱,等級,血量):
        self.角色名稱 = 名稱
        self.角色等級 = 等級
        self.角色血量 = 血量
    def 戰鬥(self):
        print("魔法攻擊")
    
    def cure(self):
        print("魔法治療")
        
    def __str__(self):
        return '({名稱},{等級},{血量})'.format(名稱=self.角色名稱,等級=self.角色等級,血量=self.角色血量)

sm = SwordsMan("Leon",20,1000)
sm.戰鬥()
揮劍攻擊

為了不再做重複的事情,將相同的事情抽出並且定義成新的類別,作為父類別。

class Role():
    def __init__(self,名稱,等級,血量):
        self.角色名稱 = 名稱
        self.角色等級 = 等級
        self.角色血量 = 血量
        
    def __str__(self):
        return '({名稱},{等級},{血量})'.format(名稱=self.角色名稱,等級=self.角色等級,血量=self.角色血量)
    
    def __repr__(self):
        return self.__str__()
    
class SwordsMan(Role):
    def 戰鬥(self):
        print("{} 進行揮劍攻擊".format(self.角色名稱))

class Magician(Role):
    def 戰鬥(self):
        print("{} 進行魔法攻擊".format(self.角色名稱))
    
    def cure(self):
        print("魔法治療")
        
sm = SwordsMan("Leon",20,1000)
sm.戰鬥()
print(sm)
mn = Magician("K",60,300)
mn.戰鬥()
Leon 進行揮劍攻擊
(Leon,20,1000)
K 進行魔法攻擊

物件多重繼承

同時需要兩個類別的功能,這時就必須要多重繼承,多重繼承由左而右
考慮一種情形,B繼承於A,C繼承於A和B, 但C需要呼叫A的init()函數時,前者會導致父類A的init()函數被調用2次。
而且子類要顯式地指定父類,不符合DRY原則。

class A():
    def __init__(self):
        print('A')
    def __del__(self):
        print("del A")

class B(A):
    def __init__(self):
        A.__init__(self)
        print('B')
        
    def __del__(self):
        print("del B")
        
class C(B, A):
    def __init__(self):
        A.__init__(self)
        B.__init__(self)
        print('C')
    def __del__(self):
        print("del C")
        
if __name__=='__main__':  
    C_Child = C()
    del C_Child
A
A
B
C
del C

物件的Super - 1

利用super()函數來調用父類別的init()等函數,每個父類都執行且執行一次,不會出現重複呼叫的情況。
在子類的實現中,不用寫出所有的父類別名字,符合DRY原則。

class A(object):
    def __init__(self):
        print('A')
    def __del__(self):
        print("del A")
class B(A):
    def __init__(self):
        super(B, self).__init__()
        print('B')
    def __del__(self):
        print("del B")
class C(B, A):
    def __init__(self):
        super(C, self).__init__()
        print('C')
    def __del__(self):
        print("del C")
if __name__=='__main__':  
    C_Child = C() 
    del C_Child
A
B
C
del C

物件的Super - 2

採用super()方式時,會自動找到第一個多繼承中的第一個父類,如果想強制呼叫其他父類的init()函數或兩個父類的同名函數時,就只能寫出父類別的名字了。

class A(object):
    def __init__(self):
        print('A')
    def __del__(self):
        print("del A")
class B(object):
    def __init__(self):        
        print('B')
    def __del__(self):
        print("del B")
class C(B, A):
    def __init__(self):
        A.__init__(self)
        super(C, self).__init__()
        print('C')
    def __del__(self):
        print("del C")
if __name__=='__main__':  
    C_Child = C() 
    del C_Child
A
B
C
del C

Python 筆記 4

Published on:

生成器 (generator)

由於記憶體是有限的,我們如果需要一個長度很長的列表,又不訪問每個元素,直接生成列表就很浪費記憶體。
#本來的list

source_list = [x*x for x in range(1,10)]
print(type(source_list))
print("List 第一個數值:",source_list[0])

#生成器產生的

generator_list = (x*x for x in range(1,10))
print(type(generator_list))
print("Generator 第一個數值:", next(generator_list))
<class 'list'>
List 第一個數值: 1
<class 'generator'>
Generator 第一個數值: 1
def fab(max): 
   n, a, b = 0, 0, 1 
   while n < max: 
       print(b)
       a, b = b, a + b 
       n = n + 1
print("一般版本:")
fab(5)

def fay(max): 
   n, a, b = 0, 0, 1 
   while n < max: 
       yield b
       a, b = b, a + b 
       n = n + 1
print("yield 版本:")

f = fay(5)
print("獨立讀取")
print(f.__next__())
print("for 連續讀取")
for i in fay(5):
    print(i)


一般版本:
1
1
2
3
5
yield 版本:
獨立讀取
1
for 連續讀取
1
1
2
3
5
x = [1,2,3,4]
y = iter(x)
print(x)
print(y)
print(next(y))
print(next(y))
[1, 2, 3, 4]
<list_iterator object at 0x0117C6B0>
1
2

裝飾器 (Decorator)

用來包裝 function、method、lambda 等任何的 callable 物件。
1. 沒有參數的版本
2. 有參數的版本
print("1. 沒有參數的版本")
def mydr(f):
    def d_f(*args, **kargs):
        print("流程1")
        result = f(*args, **kargs)
        print("流程2")
        return result
    return d_f

@mydr
def hello():
    print("打印 hello()")

hello()

print("=====================================")
print("2. 有參數的版本")
def mydr2(status):
    def one_f(f):
        def d_f(*args, **kwargs):
            print("傳入的參數:",status)
            print("流程1")
            result = f(*args, **kwargs)
            print("流程2")
            return result
        return d_f
    return one_f

@mydr2("OK")
def hello2():
    print("打印 hello2()")

hello2()
1. 沒有參數的版本
流程1
打印 hello()
流程2
=====================================
2. 有參數的版本
傳入的參數: OK
流程1
打印 hello2()
流程2

正規表示式

正規則表達式是字符一個特殊的序列,用以匹配或者尋找其他的字符串或一組字符串,正則表達式被廣泛應用於UNIX世界中。
正規式 說明及範例 比對不成立之字串
/a/ 含字母 "a" 的字串,例如 "ab", "bac", "cba" "xyz"
/a./ 含字母 "a" 以及其後任一個字元的字串,例如 "ab", "bac"(若要比對.,請使用 .) "a", "ba"
/^xy/ 以 "xy" 開始的字串,例如 "xyz", "xyab"(若要比對 ^,請使用 ^) "axy", "bxy"
/xy$/ 以"xy"結尾的字串,例如 "axy", "abxy"以 "xy" 結尾的字串 "xya", "xyb"
[13579] 包含 "1" 或 "3" 或 "5" 或 "7" 或 "9" 的字串,例如:"a3b", "1xy" "y2k"
[0-9] 含數字之字串 不含數字之字串
[a-z0-9] 含數字或小寫字母之字串 不含數字及小寫字母之字串
[a-zA-Z0-9] 含數字或字母之字串 不含數字及字母之字串
b[aeiou]t "bat", "bet", "bit", "bot", "but" "bxt", "bzt"
[^0-9] 不含數字之字串(若要比對 ^,請使用 ^) 含數字之字串
[^aeiouAEIOU] 不含母音之字串(若要比對 ^,請使用 ^) 含母音之字串
[^^] 不含 "^" 之字串,例如 "xyz", "abc" "xy^", "a^bc"

特殊字元代表意義

正規表示法的特定字元 說明 等效的正規表示法
\d 數字 [0-9]
\D 非數字 [^0-9]
\w 數字、字母、底線 [a-zA-Z0-9_]
\W 非 \w [^a-zA-Z0-9_]
\s 空白字元 [ \r\t\n\f]
\S 非空白字元 [^ \r\t\n\f]

正規表示式線上驗證 : http://rubular.com/

import re
rat = r"[a-zA-Z0-9_]+@[a-zA-Z0-9\._]+"
print("判斷是否抓取到:",re.match(rat, 'hello@admin.cc'))
print("布林狀態:",bool(re.match(rat, 'hello@admin.cc')))
print("取得字串:",re.match(rat, 'hello@admin.cc').group())
判斷是否抓取到: <_sre.SRE_Match object; span=(0, 14), match='hello@admin.cc'>
布林狀態: True
取得字串: hello@admin.cc

物件導向 (Object-Orientation,簡稱OO)

物件導向是一個抽象觀念,目的是讓程式碼可以更容易被重複使用(DRY 《Don't Repeat Yourself》 法則),以及可讀性更好,更容易理解。    
初入 物件導向 的江湖!
class Hello:
    """
    Hello 類別
    """
    
ho = Hello()
print(ho)
print(type(ho))
<__main__.Hello object at 0x01174D50>
<class '__main__.Hello'>
class Account:
    """
    Account 類別
    """
    def __init__(self, name, number, balance):
        """
        __init__ 是 Account的屬性
        """
        self.name = name
        self.number = number
        self.balance = balance

    def __del__(self):
        print("Account 類別死亡")
   
    def __str__(self):
        return '<__str__ 輸出> Account({0}, {1}, {2})'.format(
            self.name, self.number, self.balance)

at = Account('Glider', '123-4567', 1000)
print("Name:",at.name)
print("Number:",at.number)
print("Balance:",at.balance)
print(at)
del at
Name: Glider
Number: 123-4567
Balance: 1000
<__str__ 輸出> Account(Glider, 123-4567, 1000)
Account 類別死亡

Python 筆記 3

Published on:

集合 (Set)

集合類似數學中的集合,裡面包含不重複的元素值 (集合在判斷元素是否存在的效率相對較好)

a = set()
a.add(1) # { 1 }

a.add(2) # { 1, 2 }

a.add(2) # { 1, 2 }

print("長度:", len(a))
print("元素存在:", 1 in a) # True


spec = [1, 2, 3, 1, 2, 3]
print("spec list: ", spec)
set_spec = set(spec)
print("set_spec: ",set_spec)
print("結果: ",list(set_spec))
長度: 2
元素存在: True
spec list:  [1, 2, 3, 1, 2, 3]
set_spec:  {1, 2, 3}
結果:  [1, 2, 3]

列表示推導(comprehensive list)

實務上常常會需要把某個 list 轉換成另外一個 list,條件可能是只挑選其中幾個元素或是對期中某些元素進行轉換。

my_counter = [x for x in range(5) if x % 2 == 0]
print("my_counter: ", my_counter)

bined_counter = [x * x for x in my_counter]
print("bined_counter: ", bined_counter)

zeros = [0 for _ in my_counter]
print("zeros: ",zeros)

counter_dict = { x : x * x for x in range(5) }
print("counter_dict: ", counter_dict)

counter_set = { x * x for x in [1, -1] } 
print("counter_set: ", counter_set)

random_pairs = [(x, y) for x in range(10) for y in range(10)]
print("random_pairs: ", random_pairs)

a = [(x, y) for x in range(3) for y in range( x + 1, 10)]
print(a)
my_counter:  [0, 2, 4]
bined_counter:  [0, 4, 16]
zeros:  [0, 0, 0]
counter_dict:  {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
counter_set:  {1}
random_pairs:  [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6), (2, 7), (2, 8), (2, 9), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8), (3, 9), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4), (4, 5), (4, 6), (4, 7), (4, 8), (4, 9), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5), (5, 6), (5, 7), (5, 8), (5, 9), (6, 0), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6), (6, 7), (6, 8), (6, 9), (7, 0), (7, 1), (7, 2), (7, 3), (7, 4), (7, 5), (7, 6), (7, 7), (7, 8), (7, 9), (8, 0), (8, 1), (8, 2), (8, 3), (8, 4), (8, 5), (8, 6), (8, 7), (8, 8), (8, 9), (9, 0), (9, 1), (9, 2), (9, 3), (9, 4), (9, 5), (9, 6), (9, 7), (9, 8), (9, 9)]
[(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (2, 3), (2, 4), (2, 5), (2, 6), (2, 7), (2, 8), (2, 9)]

函式(function)

使用 def 來定義函式:,主要是重複使用的程式區塊。
1. Python 屬於一級函式(first-class),將函數指定給某個變數,然後把它傳給某個函數中,就像是平常把參數傳入函式一樣。
2. 函式參數預設值。
3. lambda 匿名函數使用方式(簡化寫法,前面是參數後面是操作)。

<注意!> lambda是運算式,不是陳述句,你在 : 之後的也必須是運算式,lambda中也不能有區塊,這表示一些小的運算任務你可以使用lambda

def hello():
    print("Hello Function")
    
hello()

def sum(x , y):
    return (x + y)
    
result = sum(1,2)
print("X + Y:", result)

def super_sum(fun):
    return fun(3, 2)

num = super_sum(sum)
print("傳入函式:", num)

def get_phone(phone="I8"):
    return phone

print("沒有傳值呼叫:", get_phone())
print("傳值呼叫:", get_phone("OPPO"))
Hello Function
X + Y: 3
傳入函式: 5
沒有傳值呼叫: I8
傳值呼叫: OPPO
def max(a, b):
    return a if a > b else b

print("Function:",max(10, 3))


max = lambda a, b: a if a > b else b
print("Lambda:", max(10, 3))
Function: 10
Lambda: 10

args 與 kwargs

某些狀況下我希望函式可以接受任意參數,這時可以使用 args(由無名稱參數組成的元組) 和 kwargs(由無名稱參數組成的字典)

def how_much(*args, **kwargs):
    print('args:', args)
    print('kwargs:', kwargs)
    
how_much("I8", 30000, phone='OPPO', price=22000) 
args: ('I8', 30000)
kwargs: {'phone': 'OPPO', 'price': 22000}
def phone_discount(f):
    def pd(*args, **kwargs):
        return f(*args, **kwargs)
    return pd

def phone(x, y):
    return x * y

g = phone_discount(phone)
print(g(30000, 0.9))
27000.0

Python 筆記 2

Published on:

例外狀況

若是程式出現錯誤的話會送出 exception 而掛掉,在 Python 中例外處理可以使用 try…except:

try:
    print(100/0)
except Exception as e:  
    print(e)
'''
結果: division by zero
'''

字典(Dictionary)

字典類似 map,包含鍵值與對應的值,可以快速取出對應值:

'''
宣告成dict的兩個方法
'''
dict1 = {}
dict2 = dict()

phones = {'OPPO':'R11', 'IPhone':'I8'}
phones['OPPO']
'''
結果 : R11
'''

設定數值:

phones['HTC'] = 'U11+'
len(phones)
'''
目前變數狀態: {'OPPO': 'R11', 'IPhone': 'I8', 'HTC': 'U11+'}
變數長度: 3
'''

數值檢驗方法:

  1. Try 方法
    try:
        phone = phones['LG']
    except KeyError:
        print('no phone for LG')
    '''
    結果: no phone for LG
    '''
    
  2. Get 方法
    phones.get('LG','G6')
    '''
    結果: G6
    說明: 如果沒有辦法取得 LG 的數值,則使用 G6
    '''
    
  3. If 方法
    'LG' in phones
    '''
    結果: False
    '''
    

取出所有值:

phones.keys() 
'''
所有鍵值組成的 dict_keys(['OPPO', 'IPhone', 'HTC'])
'''
phones.values()
'''
所有值組成的 dict_values(['R11', 'I8', 'U11+'])
'''
phones.items()
'''
所有鍵值組成的 dict_items([('OPPO', 'R11'), ('IPhone', 'I8'), ('HTC', 'U11+')])
'''

控制結構

If -- True -> A
   |
   -- False -> B
選擇結構 說明
if 如果條件爲真執行A
if else 如果條件為真執行A,否則執行B
if elif 多重條件選擇
if elif else 多重條件選擇,可預設執行選項
a = 2
b = 1
if a > b:
    print("a > b")
    
if a != b:
    print("a != b")
'''
結果1 : a > b
結果2 : a != b
'''

重複結構 (while)

while -- True -> A
    |     | <----|
    |
    | -- False (Exit while)

當 while 判定 True 就會執行 A ,判定爲 False ,則結束工作的執行。
此方式為重複結構,也被稱為迴圈 (loop) 。

while True:
    print("Run Loop")
  
'''
結果: 
    Run Loop
    Run Loop
    Run Loop
    Run Loop
    ...
    ...
'''

重複結構 (for)

eg. for i in range(5)
for (i<=4) True ---> A
    |       | <------|
    |
    | -- (i>4) False --> Exit for

for 為 Python 的關鍵字之一,後面接一個變數,此例中用 i ,然後接關鍵字 in ,最後是複合資料型態的資料(list,dict..),最後接冒號,若是沒有元素,迴圈自動結束。

for i in range(5):
    print(i)
  
'''
結果: 
    0
    1
    2
    3
    4
'''

進階用法 defaultdict

當你檢查一個不存在的鍵值時,用零參數函式添加一個事先設定的值

  1. 介紹一般作法
    '''
    例外處理
    '''
    data = "OPPO"
    word_counts = {}
    for word in data:
        try:
            word_counts[word] += 1
        except KeyError:
            word_counts[word] = 1
    print(word_counts)
    '''
    結果: {'O': 2, 'P': 2}
    '''
    
    '''
    使用 Get
    '''
    data = "OPPO"
    word_counts = {}
    for word in data:
        p = word_counts.get(word,0)
        word_counts[word] = p + 1
    print(word_counts)
    '''
    結果: 
    {'O': 1}
    {'O': 1, 'P': 1}
    {'O': 1, 'P': 2}
    {'O': 2, 'P': 2}
    '''
    
  2. defaultdict 作法(不用每次檢查鍵是否存在)
    from collections import defaultdict
    data = "OPPO"
    word_counts = defaultdict(int) #產生 defaultdict(<class 'int'>, {})
    
    for word in data:
        word_counts[word] += 1
    print(word_counts)
    '''
    結果: defaultdict(<class 'int'>, {'O': 2, 'P': 2})
    '''
    
    也可以使用 list 或 dict 甚至是自己定義的函式來做為 defaultdict 的零參數函式:
    pe_list = defaultdict(list)
    pe_list[0].append('OPPO') # defaultdict(<class 'list'>, {0: ['OPPO']})
    
    print(pe_list[0])
    '''
    結果: ['OPPO']
    '''
    

進階用法 Counter

Counter:可以把一系列值轉成類似 defaultdict(int) 的東西,對應到相應的數量,可以用來建立直方圖

from collections import Counter
data = "OPPO"
c = Counter([0, 1, 2, 0]) # { 0: 2, 1: 1, 2: 1 } 

word_counts = Counter(data)
print(word_counts)
'''
結果: Counter({'O': 2, 'P': 2})
'''

每個 Counter 實例都有個 most_common 的方法

from collections import Counter
data = "OPPO"
word_counts = Counter(data)
for word, count in word_counts.most_common(10):
    print(word, count)
'''
結果: 
    O 2
    P 2
'''