Code:https://github.com/lotapp/BaseCodehtml
多圖舊版:http://www.javashuo.com/article/p-guiqcmup-gr.htmlpython
在線編程:https://mybinder.org/v2/gh/lotapp/BaseCode/mastergit
在線預覽:http://github.lesschina.com/python/base/pop/4.func.htmlgithub
主要是普及一下Python基礎語法,對比着Net,新手更容易上手。web
對比學習頗有意思的,尤爲是一些底層和思路算法
原本感受函數要說的地方沒多少,細細一規劃,發現~仍是單獨拉出一篇說說吧編程
以後就進入面向對象了,函數仍是有必要了解一下的,否則到時候Class裏面的方法定義又要說了。緩存
演示的模式一直在變,剛開始讓你們熟悉一下 VSCode
,後來引入了 ipython3
交互式編程的概念app
如今就用前幾天講的 Jupyter-Notebook
來演示了(VSCode如今也有這個預覽版的插件了)less
過幾天咱們會直接 像寫文章通常的Coding,一邊寫文章一邊Code,最後還能生成須要的頁面
定義一個空函數:(不寫pass就報錯了)
# 空函數定義
def method():
pass #至關於佔位符,ifelse等等裏面都是能夠出現的
method()
# 定義一個無參函數
def get_name():
print("我叫張三")
# 調用一個無參函數
get_name()
擴:文檔說明用""" 或者'''來定義,就是以下效果
# 定義一個含參數的函數(name和age都是形參)
def show_infos(name,age):
"""打印name和age"""#函數文檔說明
print("我叫",name,"個人年齡是",age)#這種輸出方式會自動以空格鏈接字符串
# 調用一個含參數的函數
show_infos("李四",22)#實參
# 定義一個含默認參數(缺省參數)的函數(默認參數必須指向不變對象)
# 好比你設置一個list,改變了內容,則下次調用時,默認參數(缺省參數)的內容就變了,再也不是函數定義時的值了
def default_param(name,age=23):
"""age默認爲23"""
print("我叫",name,"個人年齡是",age)#這種輸出方式會自動以空格鏈接字符串
# 調用一個默認參數(缺省參數)的函數
default_param("張三")
# 定義有返回值的函數
def div_have_return(a,b):
"""計算a+b,返回計算結果"""#函數文檔說明
return a+b
# 調用有返回值的函數
result=div_have_return(1,2)
print("計算結果爲",result)
# 定義含有多個返回值的函數(利用了元組)
def div_have_returns(a,b):
"""計算a+b的和,計算a-b,並返回兩個結果"""
return (a+b),(a-b)
# 調用含有多個返回值的函數
sum,dvalue=div_have_returns(1,2)
print("sum:",sum,"D-value:",dvalue)
# 測試一下~返回多個值實際上是利用了元組
# 多返回值只是一種假象,Python函數返回的仍然是單一值~元組
test=div_have_returns(1,2)
print(test)
# 定義函數時,須要肯定函數名和參數個數
# 若是有必要,能夠先對參數的數據類型作檢查
# 函數體內部能夠用return隨時返回函數結果
# 函數執行完畢也沒有return語句時,自動return None
# 函數能夠同時返回多個值,但其實就是一個tuple
# 擴展:使用list實現
# 定義含有多個返回值的函數(利用了元組)
def div_have_returns(a,b):
"""計算a+b的和,計算a-b,並返回兩個結果"""
return [a+b,a-b]
# 調用含有多個返回值的函數
div_have_returns(1,2)
######## 經過元組、列表實現 ########
def default_some_params(nums):
"""藉助Tuple和list"""
sum=0
for item in nums:
sum+=item
return sum
# 元組傳入
default_some_params((1,2,3,4,5))
# 列表傳入
default_some_params(list(range(1,6)))
定義一個可變參數的函數(參數名字通常都是*args
)
######## 定義一個可變參數的函數(名字通常都是*args) ########
# 定義可變參數和定義一個list或tuple參數相比,僅僅在參數前面加了一個*號。
# 在函數內部,接收到的參數是一個tuple。調用該函數時,能夠傳入任意個參數(包括0個參數)
def default_params(*args):
"""定義一個可變參數,用來求全部參數的總和"""
sum=0
for item in args:
sum+=item
return sum
# 調用一個可變參數的函數
default_params(1,2,3,4,5)
# 傳一個list或者Tuple(參數前面加*)
# 傳一個元組
test_tuple=(1,2,3,4,5)
default_params(*test_tuple)
# range(1,6) ==> [1,6) ==> 1,2,3,4,5
test_list=list(range(1,6))
default_params(*test_list)
來個Main傳參的擴展,貼兩張圖便可:
定義含關鍵字參數的函數:def default_kv_params(name,age=23,**kv):
可變參數容許你傳入0個或任意個參數,這些可變參數在函數調用時自動組裝爲一個tuple
關鍵字參數容許你傳入0個或任意個含key-value
的參數,自動組裝爲一個dict
######## 調用含關鍵字參數的函數 ########
# 可變參數容許你傳入0個或任意個參數,這些可變參數在函數調用時自動組裝爲一個tuple
# 關鍵字參數容許你傳入0個或任意個含key-value的參數,自動組裝爲一個dict
def default_kv_params(name,age=23,**kv):
"""輸出輸出用戶傳參"""
print("我叫",name,"個人年齡是",age,"dict:",kv)
# 調用含關鍵字參數的函數
default_kv_params("dnt",web="www.baidu.com",qq=110)
來個 綜合案例:def default_god_params(name,age=23,*args,**kv):
須要注意py裏面的書寫格式 ==> 先定義再調用(Code參考)
#### 同時定義可變參數+關鍵字參數 ####
def default_god_params(name,age=23,*args,**kv):
"""同時有可變參數+關鍵字參數的使用方法"""
print("我叫",name,"個人年齡是",age,"list:",args,"dict:",kv)
# 調用可變參數+關鍵字參數
# 有名字給kv,沒名字給args
default_god_params("dnt",24,1,2,3,4,5,web="www.baidu.com",qq=110)
#只調用可變參數
default_god_params("dnt",24,1,2,3,4,5)
# 只調用關鍵字參數
default_god_params("dnt",web="www.baidu.com",qq=110)
#### 傳元組和字典 ####
test_tuple=(1,2,3,4,5)
test_dict={"web":"www.baidu.com","qq":110}
default_god_params(*test_tuple,**test_dict)
C#
基礎語法你們都很熟了,我貼一個註釋的Code
便可(Code在線)
VSCode
裏面若是也想像VS同樣,///
就生成註釋 ==》請安裝函數文檔註釋:XML Documentation Comments
using System;
using System.Collections.Generic;
namespace _6func
{
class Program
{
static void Main(string[] args)
{
// 交換兩數新方式
int x = 3, y = 5;
(x, y) = (y, x);
System.Console.WriteLine("{0},{1}", x, y);
#region Base
// # 定義一個空函數:
Method();
// # 定義一個無參函數
GetName();
// # 定義一個含參函數
ShowInfos("李四", 22);
// # 定義一個含默認參數(缺省參數)的函數
DefaultParam("張三");
// # 定義有返回值的函數
int result = DivHaveReturn(1, 2);
Console.WriteLine($"計算結果爲{result}");
#endregion
// # 定義含有多個返回值的函數(利用了元組)
var (sum, dvalue) = DivHaveReturns(1, 2);
Console.WriteLine($"sum:{sum},D-value:{dvalue}");
// 傳多個參數系列:
// 引用傳遞(經過元組、列表實現):擴展有可變類型和不可變類型做爲形參的對比
var list = new List<int>() { 1, 2, 3, 4, 5 };
Console.WriteLine(DefaultSomeParams(list));
Console.WriteLine(list.Count);//這就是引用傳遞的證實
// # 定義一個可變參數的函數(參數名字通常都是*args)
Console.WriteLine(DefaultParams(1, 2, 3, 4, 5));
// # 定義含關鍵字參數的函數 直接傳Dict
}
#region base
/// <summary>
/// 定義一個空函數
/// </summary>
private static void Method()
{
}
/// <summary>
/// 定義一個無參函數
/// </summary>
// private static void GetName()
// {
// Console.WriteLine("你好");
// }
//簡寫
private static void GetName() => Console.WriteLine("你好");
/// <summary>
/// 定義一個含參數的函數
/// </summary>
/// <param name="name">名字</param>
/// <param name="age">年齡</param>
// private static void ShowInfos(string name, int age)
// {
// Console.WriteLine($"我叫{name} 個人年齡是{age}");
// }
//簡寫
private static void ShowInfos(string name, int age) => Console.WriteLine($"我叫{name} 個人年齡是{age}");
/// <summary>
/// 定義一個含缺省參數的函數
/// </summary>
/// <param name="name">名字</param>
/// <param name="age">年齡默認23</param>
// private static void DefaultParam(string name, int age = 23)
// {
// Console.WriteLine($"我叫{name} 個人年齡是{age}");
// }
//簡寫
private static void DefaultParam(string name, int age = 23) => Console.WriteLine($"我叫{name} 個人年齡是{age}");
/// <summary>
/// 定義一個有返回值的函數(計算a+b,返回計算結果)
/// </summary>
/// <param name="a">num1</param>
/// <param name="b">num2</param>
// private static int DivHaveReturn(int a, int b)
// {
// return a + b;
// }
//簡寫
private static int DivHaveReturn(int a, int b) => a + b;
#endregion
/// <summary>
/// 定義含有多個返回值的函數(利用了元組)
/// 計算a+b的和,計算a-b,並返回兩個結果
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
// private static (int sum,int dValue) DivHaveReturns(int a, int b)
// {
// return ((a+b),(a-b));
// }
//簡寫
private static (int sum, int dValue) DivHaveReturns(int a, int b) => ((a + b), (a - b));
#region 傳入多個參數系列
/// <summary>
/// 利用列表實現,引用傳遞之類的C#還有ref和out,這邊就不說了
/// </summary>
/// <param name="nums"></param>
/// <returns></returns>
private static int DefaultSomeParams(List<int> numList)
{
int sum = 0;
foreach (var item in numList)
{
sum += item;
}
numList.Clear();
return sum;
}
/// <summary>
/// 定義一個可變參數的函數
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private static int DefaultParams(params int[] args)
{
int sum = 0;
foreach (var item in args)
{
sum += item;
}
return sum;
}
#endregion
}
}
# 函數遞歸調用其實就是本身調用本身,關鍵點只要考慮何時跳出便可(沒有跳出就是死循環)
# 階乘案例 n!
def factorial(n):
if n==1:
return n #跳出
elif n>1:
return n*factorial(n-1) #規律公式
print(factorial(4))
print(factorial(-4))
來個案例(實際工做中並不會本身定義,用系統自帶strip方法便可)
# 利用切片操做,實現一個trim()函數,去除字符串首尾的空格
# 跳出點==> 第一個字符和最後一個字符不是空格
def my_trim(input_str):
if input_str[0] != " " and input_str[-1] != " ":
return input_str
elif input_str[0]==" ":
return my_trim(input_str[1:])#從第二個到最後一個字符
elif input_str[-1]==" ":
return my_trim(input_str[:-1])#從第一個到倒數第二個(end_index取不到)
print(my_trim("我去 "))
print(my_trim(" 我去"))
print(my_trim(" 我去 "))
C#的遞歸我就引用一下之前的(Code)
using System;
namespace _10.遞歸案例
{
class Program
{
//一列數的規則以下: 一、一、二、三、五、八、1三、2一、34...... 求第30位數是多少, 用遞歸算法實現
static void Main(string[] args)
{
//1 2 3 4 5 n
//1 1 1+1 2+1 3+2 Fn(n-2)+Fn(n-1)
Console.WriteLine(GetNum(30));
Console.ReadKey();
}
/// <summary>
/// 遞歸就這麼理解,先找能打破重複的條件,而後就不斷的重複去吧
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
private static int GetNum(int n)
{
if (n == 1 || n == 2)
{
return 1;
}
else
{
return GetNum(n - 1) + GetNum(n - 2);
}
}
}
}
# Python對匿名函數的支持有限,只有一些簡單的狀況下可使用匿名函數
# lambda 參數: 表達式
# 來個簡單求和案例:
sum=lambda a,b: a+b
sum(1,2) #調用一下看看(有點js的感受,函數能夠直接賦值給變量,而後直接用)
來個常常用的排序案例:data_list.sort(key=lambda x:x["key"])
還有一個比較經常使用的地方 == > 當參數傳遞 def sum(a,b,func):
sum(1,2,lambda x,y: x+y)
先看案例:
# 來個實際案例,還記得list的排序嗎?
# 此次按照指定key排序(有點 SQL 裏面 order by 的感受)
data_list=[
{"name":"a張三","age":21},
{"name":"b李四","age":23},
{"name":"a王五","age":22}]
# 按照age排序
data_list.sort(key=lambda x:x["age"])
print(data_list)
# 按照name排序
data_list.sort(key=lambda x:x["name"])
print(data_list)
# 能夠看看幫助文檔
help(data_list.sort)
# 當函數的參數傳遞(有時候須要傳一個匿名方法去函數中處理某些事情)
def sum(a,b,func):
return func(a,b)
sum(1,2,lambda x,y: x+y)
有人可能會說,這個就太簡單了,沒啥好說的,(⊙o⊙)… Python
還真須要說說,來個案例給你猜結果:
# 有人可能會說,這個就太簡單了,沒啥好說的,(⊙o⊙)… Python還真須要說說
a=100
b=[1,2]
def set_num(num):
num+=num
set_num(a)
set_num(b)
# 發現全局變量a木有被修改,而b修改了
print(a)
print(b)
直接看結果吧:發現全局變量a木有被修改,而b修改了?
啥狀況呢?來個簡單案例說明下吧~
# 仍是來個簡單案例說明下吧~
a=100
def set_num(num):
a=200
set_num(a)
print(a)
這是由於,python
定義一個變量的寫法不用加類型致使的(⊙﹏⊙)
因此函數裏面a=200
,python解釋器就認爲 你定義了一個和a這個全局變量名字相同的局部變量
那怎麼用呢?global
來聲明一下全局變量便可:
# a=200,python解釋器就認爲你定義了一個和a這個全局變量名字相同的局部變量,那怎麼用呢?global來聲明一下便可
a=100
def set_num(num):
global a
a=200
set_num(a)
print(a)
總結:
在函數中不使用global
聲明全局變量不能修改全局變量 ==> 本質是不能修改全局變量的指向,即 不能將全局變量指向新的數據
對於 不可變類型的全局變量來講,因其 指向的數據不能修改,因此不使用global
時沒法修改全局變量
對於 可變類型的全局變量來講,因其 指向的數據能夠修改,因此不使用global
時也可修改全局變量
有人可能會問了,以前基礎部分自增自減說了一下:
Python分爲:可變類型:list,dict,set等等 和 不可變類型:int,str,tuple,float等等
後來Dict添加修改又提了一下,還沒太清楚怎麼辦?
不用慌,今天通通解決,先來個案例看看怎麼個可變和不可變
吧:
a="mmd"
a[0]
# 無法修改
a[0]='d'
a=['m','m','d']
a[0]
a[0]='n'
a
這個直觀吧,先這樣理解 ==> 可變就是可修改,不可變就是不可修改
其實有個小技巧:看可變不可變就看修改前和修改後的id是否相同,不一樣就是不可變,相同則是可變
在C#或者其餘語言裏面int是能夠修改的,可能對Python的int是不可變類型
有所懷疑,因此咱們驗證一下
i=1
id(i)
# 地址改變了
i+=1
id(i)
# 地址又變了
i=i+1
id(i)
能夠看到執行 i+=1
時,內存地址都會變化,更加證明了int類型是不可變類型
再來個案例
j=1
id(j) # 有沒有發現,跟一開始i的內存地址同樣了
對於不可變類型int
,不管建立多少個不可變類型,只要值相同,都指向同個內存地址
# 更直觀的來幾個案例
a=1
b=1
c=1
# 不只僅都同樣,還和全部等於1的變量地址都相同
# 這下不懷疑了吧
print(id(a))
print(id(b))
print(id(c))
不懷疑後,再來個拓展 ~ float是否同樣呢
?
來個案例看看
f1=1.2
id(f1)
# 地址變了,說明float也是不可變類型
f1+=1.0
id(f1)
可是下面部分就和int不同咯~
聲明兩個相同值的浮點型變量,查看它們的id,發現它們並非指向同個內存地址(這點和int類型不一樣)
這方面涉及Python內存管理機制,Python對int類型和較短的字符串進行了緩存,不管聲明多少個值相同的變量,實際上都指向同個內存地址
總之知道float
也是不可變類型便可
f2=1.2
f3=1.2
print(id(f2))
print(id(f3))
不可變看完了,來看看可變類型:
list1=[12,11,1]
id(list1)
# 改完仍是本身原來的地址~說明是可變類型
list1.append(0)
id(list1)
下面驗證一下:當存在多個值相同的不可變類型變量時,看看它們是否是跟可變類型同樣指向同個內存地址:
結論:當存在多個值相同的不可變類型變量時,並非指向同一個地址
# 當存在多個值相同的不可變類型變量時,並非指向同一個地址
list2=[12,11,1]
list3=[12,11,1]
print(id(list2))
print(id(list3))
老規矩,來個擴展:
想同一個地址怎麼辦?直接賦值便可(注意下面的一種狀況)
print(id(list2))
print(id(list3))
list3=list2
print(id(list3)) # 如今list3的地址和list2地址同樣了
# 注意這種狀況,若是對其中一個list修改,那麼另外一個也就跟着被修改了
# 任意一個List進行修改,都會影響另一個List的值
list2.append(0)
print(list2)
print(list3)
print(id(list2))
print(id(list3))
關於可變類型和不可變類型今天就到這吧,下次還會再說更高深的知識點的,盡請期待哦~
下面就進入驗證擴展系列,看看一些概念:
1.以前不少資料說python3的匿名函數裏不能調用print函數,本身測試下:
# 以前不少資料說py3匿名函數裏不能調用print函數,本身測試下
# 定義一個無參匿名函數
printf=lambda:print("I Love You")
printf()
2.可變類型與不可變類型的變量分別做爲函數參數的區別
感到疑惑能夠看以前的運算符擴展(點我)
上面講完可變和不可變再看這個就過輕鬆了~
Python中函數參數都是引用傳遞
對於不可變類型,因變量不能修改,因此運算不會影響到變量自身
而對於可變類型來講,函數體中的運算有可能會更改傳入的參數變量
# 可變類型與不可變類型的變量分別做爲函數參數的區別
def default_some_params(nums):
nums+=nums
test_num=1
default_some_params(test_num)
test_num
test_list=list(range(1,6))
default_some_params(test_list)
test_list
3.函數名能不能重複的問題
在C#或者Java之中,能不能重載:具備不一樣的參數的類型或參數的個數【跟返回值不要緊】
結論:函數名不能重名
# 函數名能不能重複的問題(能不能重載:具備不一樣的參數的類型或參數的個數)
def test():
pass
def test(a,b):
return a+b
test(1,2)
test() #前一個直接被後一個覆蓋掉了
4.此次說說兩個有趣的擴展
交換兩數這個以前就說過了,這邊再提一下:
# 交換兩數~元組的方式
a=1
b=2
a,b=b,a # 寫全:(a,b)=(b,a)
print(a)
print(b)
C#的再回顧一下:
int x = 1, y = 2;
(x, y) = (y, x);
Console.WriteLine("x: " + x + " y: " + x);
5.eval
(和js裏面的eval差很少):不太建議使用
# 2.eval(和js裏面的eval差很少):
input_str=input("請輸入:")
print(input_str)
eval(input_str)