精华内容
下载资源
问答
  • Matlab的各校ppt历年题目及获奖论文-建模题目及论文3.rar ppt包括清华大学、浙江大学、国防科技大学、纽约大学 论文主要是全国的,还有地区的学校的,以及全美的。共334M
  • 120matlab题目.zip

    2021-07-04 13:27:20
    MATLAB 期末考核 一、已知矩阵 (1)求、、; (2)求A每行、每列元素之和,所有元素之和; (3)将矩阵A扩充到6*6阶矩阵,第6行和第6列元素全为10; (4)提取A中所有偶数列组成新的矩阵; (5)将矩阵A进行...
  • 较为详细的MUSIC算法原理及MATLAB实现

    万次阅读 多人点赞 2019-09-11 10:58:54
    {e^{-j(M-1)\varphi_1}} & {e^{-j(M-1)\varphi_2}} & \cdots & {e^{-j(M-1)\varphi_D}} \\ \end{matrix} \right] A = [ a ( θ 1 ​ ) , a ( θ 2 ​ ) , . . . a ( θ D ​ ) ] T = ⎣ ⎢ ⎢ ⎢ ⎡ ​ 1 e − j ...

    DOA估计算法

    DOA(Direction Of Arrival)波达方向定位技术主要有ARMA谱分析、最大似然法、熵谱分析法和特征分解法,特征分解法主要有MUSIC算法、ESPRIT算法WSF算法等。
    MUSIC (Multiple Signal Classification)算法,即多信号分类算法,由Schmidt等人于1979年提出。MUSIC算法是一种基于子空间分解的算法,它利用信号子空间和噪声子空间的正交性,构建空间谱函数,通过谱峰搜索,估计信号的参数。对于声源定位来说,需要估计信号的DOA。MUSIC算法对DOA的估计有很高的分辨率,且对麦克风阵列的形状没有特殊要求,因此应用十分广泛。
    在这里插入图片描述

    运用矩阵的定义,可得到更为简洁的表达式:

    X = A S + N X=AS+N X=AS+N

    式中

    X = [ x 1 ( t ) , x 2 ( t ) , . . . x M ( t ) ] T X=[x_1(t),x_2(t),...x_M(t)]^T X=[x1(t),x2(t),...xM(t)]T
    S = [ S 1 ( t ) , S 2 ( t ) , . . . S D ( t ) ] T S=[S_1(t),S_2(t),...S_D(t)]^T S=[S1(t),S2(t),...SD(t)]T
    A = [ a ( θ 1 ) , a ( θ 2 ) , . . . a ( θ D ) ] T A=[a(\theta_1),a(\theta_2),...a(\theta_D)]^T A=[a(θ1),a(θ2),...a(θD)]T
    N = [ n 1 ( t ) , n 2 ( t ) , . . . n M ( t ) ] T N=[n_1(t),n_2(t),...n_M(t)]^T N=[n1(t),n2(t),...nM(t)]T

    X X X为阵元的输出, A A A为方向响应向量, S S S是入射信号, N N N表示阵列噪声。

    其中 φ k = 2 π d λ s i n θ k \varphi_k=\frac{2\pi d}{\lambda}sin\theta_k φk=λ2πdsinθk

    A = [ a ( θ 1 ) , a ( θ 2 ) , . . . a ( θ D ) ] T = [ 1 1 ⋯ 1 e − j φ 1 e − j φ 2 ⋯ e − j φ D ⋮ ⋮ ⋱ ⋮ e − j ( M − 1 ) φ 1 e − j ( M − 1 ) φ 2 ⋯ e − j ( M − 1 ) φ D ] A=[a(\theta_1),a(\theta_2),...a(\theta_D)]^T=\left[ \begin{matrix} 1 & 1 & \cdots & 1 \\ {e^{-j\varphi_1}} & {e^{-j\varphi_2}} & \cdots & {e^{-j\varphi_D}} \\ \vdots & \vdots & \ddots & \vdots \\ {e^{-j(M-1)\varphi_1}} & {e^{-j(M-1)\varphi_2}} & \cdots & {e^{-j(M-1)\varphi_D}} \\ \end{matrix} \right] A=[a(θ1),a(θ2),...a(θD)]T=1ejφ1ej(M1)φ11ejφ2ej(M1)φ21ejφDej(M1)φD
    x m ( t ) x_m(t) xm(t)进行N点采样,要处理的问题就变成了通过输出信号 x m ( t ) x_m(t) xm(t)的采样 { x m ( i ) = 1 , 2 , . . . , M } \{ x_m (i)=1,2,...,M\} {xm(i)=1,2,...,M}估计信号源的波达方向角 θ 1 , θ 2 . . . θ D \theta_1,\theta_2...\theta_D θ1,θ2...θD,由此可以很自然的将阵列信号看作是噪声干扰的若干空间谐波的叠加,从而将波达方向估计问题与谱估计联系起来。
    对阵列输出X做相关处理,得到其协方差矩阵

    R x = E [ X X H ] R_x=E[XX^H] Rx=E[XXH]

    其中 H H H表示矩阵的共轭转置。
    根据已假设信号与噪声互不相关、噪声为零均值白噪声,因此可得到:

    R x = E [ ( A S + N ) ( A S + N ) H ] = A E [ S S H ] A H + E [ N N H ] = A R S A H + R N R_x=E[(AS+N)(AS+N)^H] =AE[SS^H]A^H+E[NN^H]=AR_SA^H+R_N Rx=E[(AS+N)(AS+N)H]=AE[SSH]AH+E[NNH]=ARSAH+RN
    其中 R s = E [ S S H ] R_s=E[SS^H] Rs=E[SSH]称为信号相关矩阵

    R N = σ 2 I R_N=\sigma^2I RN=σ2I是噪声相关阵

    σ 2 \sigma^2 σ2是噪声功率

    I I I M × M M\times M M×M阶的单位矩阵

    在实际应用中通常无法直接得到 R x R_x Rx,能使用的只有样本的协方差矩阵:
    R x ^ = 1 N ∑ i = 1 N X ( i ) X H ( i ) \hat{R_x}=\frac{1}{N} \sum_{i=1}^{N}X(i)X^H (i) Rx^=N1i=1NX(i)XH(i) R x ^ \hat{R_x} Rx^ R x R_x Rx的最大似然估计。

    当采样数 N → ∞ N\to\infty N,他们是一致的,但实际情况将由于样本数有限而造成误差。根据矩阵特征分解的理论,可对阵列协方差矩阵进行特征分解,首先考虑理想情况,即无噪声的情况: R x = A R s A H R_x=AR_sA^H Rx=ARsAH,对均匀线阵,矩阵A由
    A = [ a ( θ 1 ) , a ( θ 2 ) , . . . a ( θ D ) ] T = [ 1 1 ⋯ 1 e − j φ 1 e − j φ 2 ⋯ e − j φ D ⋮ ⋮ ⋱ ⋮ e − j ( M − 1 ) φ 1 e − j ( M − 1 ) φ 2 ⋯ e − j ( M − 1 ) φ D ] A=[a(\theta_1),a(\theta_2),...a(\theta_D)]^T=\left[ \begin{matrix} 1 & 1 & \cdots & 1 \\ {e^{-j\varphi_1}} & {e^{-j\varphi_2}} & \cdots & {e^{-j\varphi_D}} \\ \vdots & \vdots & \ddots & \vdots \\ {e^{-j(M-1)\varphi_1}} & {e^{-j(M-1)\varphi_2}} & \cdots & {e^{-j(M-1)\varphi_D}} \\ \end{matrix} \right] A=[a(θ1),a(θ2),...a(θD)]T=1ejφ1ej(M1)φ11ejφ2ej(M1)φ21ejφDej(M1)φD
    所定义的范德蒙德矩阵,只要满足 θ i ≠ θ j , i ≠ j \theta_i\neq \theta_j,i\neq j θi=θj,i=j,则他的各列相互独立。

    R s R_s Rs为非奇异矩阵 R a n k ( R s ) = D Rank(R_s)=D Rank(Rs)=D,各信号源两两不相干,且 M > D M>D M>D,则 r a n d ( A R s A H ) = D rand(AR_sA^H)=D rand(ARsAH)=D

    由于 R x = E [ X X H ] R_x=E[XX^H] Rx=E[XXH],有:

    R s H = R x R_s^H=R_x RsH=Rx

    R s R_s Rs为Hermite矩阵,它的特性是都是实数,又由于 R s R_s Rs为正定的,因此 A R s A … … H AR_sA……H ARsAH为半正定的,它有D个正特征值和 M − D M-D MD个零特征值。

    再考虑有噪声存在的情况

    R x = A R s A H + σ 2 I R_x=AR_sA^H+\sigma^2I Rx=ARsAH+σ2I

    由于 σ 2 > 0 \sigma^2>0 σ2>0 R x R_x Rx为满秩阵,所以 R x R_x Rx有M个正实特征值 λ 1 , λ 2 . . . λ M \lambda_1,\lambda_2...\lambda_M λ1,λ2...λM

    分别对应于M个特征向量 v 1 , v 2 . . . v M v_1,v_2...v_M v1,v2...vM。又由于 R x R_x Rx为Hermite矩阵,所以各特征向量是正交的,即: v i H v j = 0 , i ≠ j v_i^Hv_j=0,i\neq j viHvj=0,i=j与信号有关的特征值只有D个,分别等于矩阵 A R s A H AR_sA^H ARsAH的各特征值与 σ 2 \sigma^2 σ2之和,其余 M − D M-D MD个特征值为 σ 2 \sigma^2 σ2,即 σ 2 \sigma^2 σ2 R R R的最小特征值,它是 M − D M-D MD维的,对应的特征向量 v i , i = 1 , 2 , . . . , M v_i,i=1,2,...,M vi,i=1,2,...,M中,也有D个是与信号有关的,另外 M − D M-D MD个是与噪声有关的,可利用特征分解的性质求出信号源的波达方向 θ k \theta_k θk

    MUSIC算法的原理及实现

    通过对协方差矩阵的特征值分解,可得到如下结论:

    将矩阵 R x R_x Rx的特征值进行从小到大的排序,即 λ 1 ≥ λ 2 ≥ . . . ≥ λ M > 0 \lambda_1 \geq \lambda_2\geq...\geq\lambda_M>0 λ1λ2...λM>0,其中D个较大的特征值对应于信号, M − D M-D MD个较小的特征值对应于噪声。

    矩阵 R x R_x Rx的属于这些特征值的特征向量也分别对应于各个信号和噪声,因此可把 R x R_x Rx的特征值(特征向量)划分为信号特征(特征向量)与噪声特征(特征向量)。

    λ i \lambda_i λi R x R_x Rx的第 i i i个特征值, v i v_i vi是与 λ i \lambda_i λi个相对应的特征向量,有:

    R x v i = λ i v i R_xv_i=\lambda_iv_i Rxvi=λivi

    再设 λ i = σ 2 \lambda_i=\sigma^2 λi=σ2 R x R_x Rx的最小特征值 R x v i = σ 2 v i i = D + 1 , D + 2... M R_xv_i=\sigma^2v_i i=D+1,D+2...M Rxvi=σ2vii=D+1,D+2...M

    R x = A R s A H + σ 2 I R_x=AR_sA^H+\sigma^2I Rx=ARsAH+σ2I代入可得 σ 2 v i = ( A R s A H + σ 2 I ) v i \sigma^2v_i=(AR_sA^H+\sigma^2I)v_i σ2vi=(ARsAH+σ2I)vi

    将其右边展开与左边比较得:

    A R s A H v i = 0 AR_sA^Hv_i=0 ARsAHvi=0

    A H A A^HA AHA D ∗ D D*D DD维的满秩矩阵, ( A H A ) − 1 (A^HA)^{-1} (AHA)1存在;

    R s − 1 R_s^{-1} Rs1同样存在,则上式两边同乘以 R s − 1 ( A H A ) − 1 A H R_s^{-1}(A^HA)^{-1}A^H Rs1(AHA)1AH

    有:

    R s − 1 ( A H A ) − 1 A H A R s A H v i = 0 R_s^{-1}(A^HA)^{-1}A^HAR_sA^Hv_i=0 Rs1(AHA)1AHARsAHvi=0

    于是有

    A H v i = 0 , i = D + 1 , D + 2 , . . . , M A^Hv_i=0,i=D+1,D+2,...,M AHvi=0i=D+1,D+2,...,M

    上式表明:噪声特征值所对应的特征向量(称为噪声特征向量) v i v_i vi,与矩阵 A A A的列向量正交,而 A A A的各列是与信号源的方向相对应的,这就是利用噪声特征向量求解信号源方向的出发点。

    用各噪声特征向量为例,构造一个噪声矩阵 E n E_n En:

    E n = [ v D + 1 , v D + 2 , . . . v M ] E_n=[v_{D+1},v_{D+2},...v_{M}] En=[vD+1,vD+2,...vM]

    定义空间谱 P m u ( θ ) P_{mu}(\theta) Pmu(θ):

    P m u ( θ ) = 1 a H ( θ ) E n E n H a ( θ ) = 1 ∥ E n H a ( θ ) ∥ 2 P_{mu}(\theta)=\frac{1}{{a^H}(\theta)}E_nE_n^Ha(\theta)=\frac{1}{\Vert E_n^Ha(\theta)\Vert^2} Pmu(θ)=aH(θ)1EnEnHa(θ)=EnHa(θ)21

    该式中分母是信号向量和噪声矩阵的内积,当 a ( θ ) a(\theta) a(θ) E n E_n En的各列正交时,该分母为零,但由于噪声的存在,它实际上为一最小值,因此 P m u ( θ ) P_{mu}(\theta) Pmu(θ)有一尖峰值,由该式,使 θ \theta θ变化,通过寻找波峰来估计到达角。

    MUSIC算法实现的步骤

    1.根据N个接收信号矢量得到下面协方差矩阵的估计值:

    R x = 1 N ∑ i = 1 N X ( i ) X H ( i ) R_x=\frac{1}{N} \sum_{i=1}^NX(i)X^H(i) Rx=N1i=1NX(i)XH(i)

    对上面得到的协方差矩阵进行特征分解

    R x = A R s A H + σ 2 I R_x=AR_sA^H+\sigma^2I Rx=ARsAH+σ2I

    2.按特征值的大小排序将与信号个数 D D D相等的特征值和对应的特征向量看做信号部分空间,将剩下的 M − D M-D MD个特征值和特征向量看做噪声部分空间,得到噪声矩阵 E n E_n En:

    A H v i = 0 , i = D + 1 , D + 2 , . . . , M A^Hv_i=0,i=D+1,D+2,...,M AHvi=0i=D+1,D+2,...,M

    E n = [ v D + 1 , v D + 2 , . . . v M ] E_n=[v_{D+1},v_{D+2},...v_{M}] En=[vD+1,vD+2,...vM]

    3.使 θ \theta θ变化,按照式

    P m u ( θ ) = 1 a H ( θ ) E n E n H a ( θ ) P_{mu}(\theta)=\frac{1}{{a^H}(\theta)E_nE_n^Ha(\theta)} Pmu(θ)=aH(θ)EnEnHa(θ)1

    来计算谱函数,通过寻求峰值来得到波达方向的估计值。

    clear; close all;
    %%%%%%%% MUSIC for Uniform Linear Array%%%%%%%%
    derad = pi/180;      %角度->弧度
    N = 8;               % 阵元个数        
    M = 3;               % 信源数目
    theta = [-30 0 60];  % 待估计角度
    snr = 10;            % 信噪比
    K = 512;             % 快拍数
     
    dd = 0.5;            % 阵元间距 
    d=0:dd:(N-1)*dd;
    A=exp(-1i*2*pi*d.'*sin(theta*derad));  %方向矢量
    
    %%%%构建信号模型%%%%%
    S=randn(M,K);             %信源信号,入射信号
    X=A*S;                    %构造接收信号
    X1=awgn(X,snr,'measured'); %将白色高斯噪声添加到信号中
    % 计算协方差矩阵
    Rxx=X1*X1'/K;
    % 特征值分解
    [EV,D]=eig(Rxx);                   %特征值分解
    EVA=diag(D)';                      %将特征值矩阵对角线提取并转为一行
    [EVA,I]=sort(EVA);                 %将特征值排序 从小到大
    EV=fliplr(EV(:,I));                % 对应特征矢量排序
                     
     
    % 遍历每个角度,计算空间谱
    for iang = 1:361
        angle(iang)=(iang-181)/2;
        phim=derad*angle(iang);
        a=exp(-1i*2*pi*d*sin(phim)).'; 
        En=EV(:,M+1:N);                   % 取矩阵的第M+1到N列组成噪声子空间
        Pmusic(iang)=1/(a'*En*En'*a);
    end
    Pmusic=abs(Pmusic);
    Pmmax=max(Pmusic)
    Pmusic=10*log10(Pmusic/Pmmax);            % 归一化处理
    h=plot(angle,Pmusic);
    set(h,'Linewidth',2);
    xlabel('入射角/(degree)');
    ylabel('空间谱/(dB)');
    set(gca, 'XTick',[-90:30:90]);
    grid on;
    

    实现结果

    在这里插入图片描述

    展开全文
  • Matlab的各校ppt历年题目及获奖论文-建模题目及论文2.rar ppt包括清华大学、浙江大学、国防科技大学、纽约大学 论文主要是全国的,还有地区的学校的,以及全美的。共334M
  • Matlab的各校ppt历年题目及获奖论文-建模题目及论文1.rar ppt包括清华大学、浙江大学、国防科技大学、纽约大学 论文主要是全国的,还有地区的学校的,以及全美的。共334M
  • matlab 考试题目及答案

    2013-05-14 18:33:55
    实验一 MATLAB软件操作练习 一、 实验目的 1. 熟悉MATLAB软件的基本操作; 2. 学会用MATLAB做基本数学计算 ...1.学会编写MATLABM文件; 2.熟悉MATLAB程序设计的基本方法; 3. 学会利用MATLAB绘制二维图形。
  • //@TOC 前言 直接扩频序列调制是用速率很高的伪噪声码序列与信息码序列模二相加(波形相乘)后得到复合码序列,...用户1扩频加扰调制高斯信道walsh码扩频M序列加扰载波调制高斯白噪声高斯信道用户2相加解调去扰用户1...

    前言

    直接扩频序列调制是用速率很高的伪噪声码序列与信息码序列模二相加(波形相乘)后得到复合码序列,用复合码序列去控制载波相位,从而获得直接扩频序列信号的。直接扩频通信具有低截获概率、抗干扰能力强以及易于实现码分多址等优点,在抗干扰通信及民用移动通信中都得到了广泛的应用。

    文章迭代更新

    文章进行了大改
    发现了为什么振幅是0.2和0.4时,系统无法正常工作的原因。因为bitMultiple函数把运算结果格式转换成了int8,导致精度大量失真!当时转换格式是为内存空间与运行速度做打算,结果今天发现做了负优化!修改后,发现载波振幅对于系统的误码率曲线几乎无影响。
    另外,解调函数也做了修改,会根据输入自动计算判决阈值,解决了之前人为设定阈值
    的局限,阈值采用正态分布解算法,详见demodulate函数内注释。
    新版修改了以下函数:
    1. bitMultiple
    2. demodulate
    3. 新增arrayGroupSum函数

    仿真流程图

    用户1
    扩频
    加扰
    调制
    高斯信道
    walsh码
    扩频
    M序列
    加扰
    载波
    调制
    高斯白噪声
    高斯信道
    用户2
    相加
    解调
    去扰
    用户1解扩
    用户2解扩
    还原信号1
    还原信号2

    关键技术细节

    1. 仿真中,用户码元使用双极性(1和-1)码。
    2. 代码的最后通过还原信号与码元做对比,计算误码率,来评价通信质量的好坏。
    3. 为了研究信噪比对误码率的影响,代码中用了多线程,针对不同的信噪比进行解调去扰解扩,计算不同信噪比下的误码率。
    4. 为了研究载波振幅对信噪比——误码率曲线的影响,增加了振幅的迭代。

    扩频解扰解扩部分

    1. 采用64阶的walsh码矩阵,由walsh函数产生。
    2. 两个用户使用同一扩频矩阵的不同相位(实际上是不同一行)进行扩频。
    3. 扩频时,首先对用户码元按照扩频增益,进行周期延拓,然后点乘扩频码,实现扩频。
    4. 解扩时,首先对输入的去扰后的码按扩频时一样的相位对应点乘扩频码,然后进行判决。

    加扰去扰部分

    1. 加扰采用的是5阶的M序列,反馈系数为67(八进制)。
    2. 加扰同样采用点乘,输入码元1:1地点乘加扰码。
    3. 因为加扰码具有很高的自相关性,所以去扰时只需执行加扰时一样的操作即可。

    加扰原理图

    加扰原理图

    调制解调部分

    1. 调制采用BPSK(二进制移相键控)调制。
    2. 调制所使用的载波为正弦波,通过对其等间隔采样形成离散样值。
    3. 调制时,一个加扰后的码元对应相乘一串正弦波的周期采样值,把相乘结果汇总后就是调制后的结果
    4. 解调时,把一个码元所对应的一串正弦波的周期采样值与载波采样值进行点乘,根据点乘结果中,正数、负数还是零多,判决这是什么码元。

    调制原理图

    调制原理图

    解调原理图

    解调原理图

    高斯信道部分

    1. 使用matlab自带的函数awgn(input,snr(dB),inputPower)
    2. 只要传入需要加高斯噪声的信号,信噪比还有输入信号的功率,即可返回添加了高斯白噪声的信号。

    实验结果

    扩频增益为10时,walsh矩阵为64阶时,不同振幅下信噪比误码率曲线

    扩频增益为10时,walsh矩阵为64阶时,不同振幅下信噪比误码率曲线

    扩频增益为20时,walsh矩阵为64阶时,不同振幅下信噪比误码率曲线

    扩频增益为20时,walsh矩阵为64阶时,不同振幅下信噪比误码率曲线
    以上两次实验结果显示,载波振幅对于系统性能无明显影响,这是文章改版前的一个很大的错误!在此笔者向各位读者道歉。

    误码率随信噪比的变化曲线

    误码率随信噪比的变化曲线
    观察以上曲线可以发现,随着信噪比的上升,误码率以近似于抛物线的形式在不断下降,并最终等于0,这足以证明本次直接序列扩频系统仿真符合预期结果。

    源代码

    可以修改的参数

    1. 轮回次数。通过修改轮回次数,获得更好的曲线,或者更快的代码运行速度,代码运行参考速度:i7-4790:实测速率9.8秒/轮回 @1280*2&1280码元20&10扩频增益。
    2. 用户1的码元数量与扩频增益、用户2的码元数量与扩频增益。修改时注意两用户的码元必须是walsh码阶数的增数倍,同时要保证:用户1的码元数量 * 用户1的扩频增益=用户2的码元数量 * 用户2的扩频增益。
    3. walsh码的阶数。但walsh码阶数必须大于扩频增益。
    4. 用户1扩频相位、用户2扩频相位。注意相位必须1到64之间取值,两个用户的取值不能一样。
    5. M序列阶数与返回系数。反馈系数取值有相关要求,详见百度,作为参数传入时要以八进制表示。
    6. 半个载波周期的采样点数。
    7. 最小最大信噪比,以及其尝试步进。
    8. 最小最大载波振幅,以及其尝试步进。

    !下载链接!

    链接:https://pan.baidu.com/s/14KNoWlD7UyC9WAEza63W5A
    提取码:qg1y

    核心代码

    主函数

    main.m

    %{
        本函数是整个仿真的主函数,用于研究在移动通信时,信噪比对误码率的影响
    首先生成随机双极性码,然后经过扩频,加扰,BPSK调制,加高斯白噪声,混合
    然后模拟接收端的解调,去扰,解扩,判决。
        通过比较接收端判决输出与原来的码元,计算出误码率,首先通信系统的仿真
    以及误码率-信噪比的变化曲线的绘制.
    2019/11/22(以上)
        在当前版本中,添加了对信噪比&误码率曲线随BPSK调制载波振幅变化而变化
    的相关研究功能。因为实际发现,之前的代码中曲线会在-20dB到0dB处出现平缓现象,
    实际排查发现是载波的振幅导致的。振幅研究结果发现:振幅小于0.4时,系统无法正常
    工作!其误码率曲线在后期随着信噪比的增加呈现反常膨胀!
    ^-^想要得到抛物线,只有在载波振幅为1的时候。^-^,不然随着振幅的增加,曲线曲线趋于平缓的信噪比范围会越大;
    同时发现大于0.6的曲线会近似相交于某一点,交点前同等信噪比下振幅高的误码率低,但在交点后
    ***同等的信噪比下振幅小的误码率反而低!!!***
        在本版本中,walsh矩阵的所有码元都被用于扩频,没有使用前一版的矩阵截取方法,
    规避了鬼魅版的非严格正交问题,但前面的截取版本恰恰说明非严格正交对本系统影响曲线
    的影响并不是很大,但却可以使得系统能在更低的误码率下工作。
        至此,代码已经经历10次版本迭代。
    2019/12/1(以上)
        第二次答辩,仍出现部分平滑问题,并且老师说系统性能太好了,与实际系统不符,并且
    曲线不应该受振幅的影响,基于此再对代码做修改,计算了输入信号的平均功率,作为第3
    个参数传给awgn,否则awgn会把输入信号的功率视为0dBW!现在曲线基本重合。但0.20.4
    的问题仍未解决!
        至此,程序第11次版本迭代
    2019/12/2(以上)
        第十二次迭代。
        发现了为什么振幅是0.20.4时,系统无法正常工作的原因,是因为
    bitMultiple函数把运算结果格式转换成了int8,导致精度大量失真!当时转换格式是为
    内存空间与运行速度做打算,结果今天发现做了负优化!修改后,发现载波振幅对于系统
    的误码率曲线几乎无影响。
        另外,解调函数也做了修改,会根据输入自动计算判决阈值,解决了之前人为设定阈值
    的局限,阈值采用正态分布解算法,详见demodulate函数内注释。
    2020/7/1(以上)
        i7-4790:实测速率9.8/轮回 @1280*2&1280码元20&10扩频增益
    %}
    clear variable;
    close all;
    
    mulTimes = 5;  %轮回次数
    
    walshOrder = 64;    %walsh码的阶数,必须大于扩频增益
    
    N1 = 1280*2;   %用户1码元数量
    N2 = 1280;   %用户2码元数量
    
    user1SPgain = 10;  %用户1的扩频增益
    user2SPgain = 20;  %用户2的扩频增益
    
    %记录两个用户的walsh相位,注意相位必须在164之间取值
    %两个用户的取值不能一样
    user1Phase = 2; %用户1的相位
    user2Phase = 16; %用户2的相位
    
    %加扰使用的m序列的参数
    mOrder = 5; %级数5级
    feedBack = 67;%反馈系数67
    
    %调整时,半个周期的采样点数
    samplePiont = 4;
    
    %生成需要使用的walsh码
    walshCode = walsh(walshOrder);
    
    %针对低性能电脑做优化,采取以时间换取空间的思路
    maxSnr = 20;    %尝试的最大信噪比
    minSnr = -20;   %尝试的最小信噪比
    div = 1;      %信噪比的尝试步进
    maxTime = (maxSnr-minSnr)/div;  %尝试次数
    timesUser1Acc = zeros(mulTimes,maxTime);
    timesUser2Acc = zeros(mulTimes,maxTime);
    
    %生成双极性码片
    user1 = genBipolar(N1);
    user2 = genBipolar(N2);   
    
    %扩频
    spread1 = spreadSpectrum(user1,walshCode,user1SPgain,user1Phase);
    spread2 = spreadSpectrum(user2,walshCode,user2SPgain,user2Phase);
    
    %加扰
    Mseq1 = MseqGen(mOrder,feedBack); %用户1加扰用的m序列
    Mseq2 = MseqGen(mOrder,feedBack); %用户2加扰用的m序列
    user1scarm = scarmbling(spread1,Mseq1);
    user2scarm = scarmbling(spread2,Mseq2);
    
    maxAmp = 1.2;    %尝试的最大载波振幅
    minAmp = 0.2;   %尝试的最小载波振幅
    divAmp = 0.2;      %载波振幅的尝试步进
    maxTimesAmp = floor((maxAmp-minAmp)/divAmp);  %振幅尝试次数
    
    ampRecords1 = zeros(maxTimesAmp,maxTime);
    ampRecords2 = zeros(maxTimesAmp,maxTime);
    
    for amp = 1:maxTimesAmp %测试不同的载波振幅下的曲线
        
        fprintf('目前正在第%d个振幅\n',amp);
    
        %调制BPSK
        %生成载波,两用户使用同一个载波
        carrier = (minAmp + divAmp*(amp-1))*sin(0:(pi/samplePiont):(2*pi-2*pi/samplePiont));
        user1modulate = modulate(user1scarm,carrier);
        user2modulate = modulate(user2scarm,carrier);
        
        %计算载波功率
        power = powerCnt(carrier);
        
        for times = 1:mulTimes
    
            fprintf('目前正在第%d个轮回\n',times);
    
            user1Acc = zeros(1,maxTime);
            user2Acc = zeros(1,maxTime);
    
            parfor index = 1:maxTime 
                snr = minSnr + (index-1)*div; %加在发送信号上的高斯噪声的信噪比(dBW)
                            
                %通过高斯信道,添加高斯噪声
                user1send = awgn(user1modulate,snr,power);
                user2send = awgn(user2modulate,snr,power);
    
                %接收方
                receive = user1send + user2send; %收到混合起来的信号
    
                %解调
                demodulateRes = demodulate(receive,carrier);
    
                %去扰
                user1Descarm = deScarmbling(demodulateRes,Mseq1);
                user2Descarm = deScarmbling(demodulateRes,Mseq2);
    
                %解扩
                user1deDS = deSpreadSpectrum(user1Descarm,walshCode,user1SPgain,user1Phase);
                user2deDS = deSpreadSpectrum(user2Descarm,walshCode,user2SPgain,user2Phase);
    
                %计算误码率
                [~,user1Accuracy] = compare(user1,user1deDS);
                [~,user2Accuracy] = compare(user2,user2deDS);
                user1Acc(index) = 1-user1Accuracy;
                user2Acc(index) = 1-user2Accuracy;
            end
            timesUser1Acc(times,:) = user1Acc;
            timesUser2Acc(times,:) = user2Acc;
        end
        %总结统计多次实验的结果
        for i = 1:maxTime
            user1Acc(i) = mean(timesUser1Acc(:,i));
            user2Acc(i) = mean(timesUser2Acc(:,i));
        end
        ampRecords1(amp,:) = user1Acc;
        ampRecords2(amp,:) = user2Acc;
    end
    
    %误码率随信噪比的变化曲线
    figure(1);
    X1 = (minSnr:div:maxSnr-div);
    semilogy(X1,ampRecords1(5,:),'b');
    xlabel('信噪比(dB)');
    ylabel('误码率');
    title('误码率随信噪比的变化曲线');
    hold on;
    semilogy(X1,ampRecords2(5,:),'g');
    legend('用户1(扩频增益10)','用户2(扩频增益20)');
    
    %用户1振幅不同的误码率随信噪比的变化曲线
    figure(2);
    for i = 1:maxTimesAmp
        semilogy(X1,ampRecords1(i,:));
        hold on;
    end
    xlabel('信噪比(dB)');
    ylabel('误码率');
    title('用户1振幅不同的误码率随信噪比的变化曲线');
    legend('0.2','0.4','0.6','0.8','1.0');
    
    %用户2振幅不同的误码率随信噪比的变化曲线
    figure(3);
    for i = 1:maxTimesAmp
        semilogy(X1,ampRecords2(i,:));
        hold on;
    end
    xlabel('信噪比(dB)');
    ylabel('误码率');
    title('用户2振幅不同的误码率随信噪比的变化曲线');
    legend('0.2','0.4','0.6','0.8','1.0');
    

    walsh码生成

    walsh.m

    % 产生 Walsh函数通用函数
    % 参数N表示Walsh函数阶数,N不是2的幂时,通过向无穷大取整使得所得Walsh阶数为2的幂
    function [walsh]=walsh(N)
        M = ceil(log2(N));
        wn = 0;
        for i = 1:M
            w2n = [wn,wn;wn,~wn];
            wn = w2n;
        end
        wn(wn == 0) = -1;
        walsh = int8(wn);
    end
    

    M序列生成

    MseqGen.m

    %M序列发生器
    %order:阶数
    %setBakc:反馈系数
    function res = MseqGen(order,feedBack)
        res = zeros(2^order-1,order);
        feedBack = Oct2Bin(feedBack);
        feedBack = feedBack(2:6);
        temp = rand(1,order);
        temp(temp < 0.5) = 0;
        temp(temp >= 0.5) = 1;
        res(1,:) = temp;
        for i = 2:2^order-1
            newBit = sum(res(i-1,feedBack == 1));
            newBit = mod(newBit,2);
            for j = 1:order-1
                res(i,j+1) = res(i-1,j);
            end
            res(i,1) = newBit;
        end
        res(res == 0) = -1;
    end
    

    扩频模块

    spreadSpectrum.m

    %扩频函数
    %userCode:需要扩频的用户码元
    %PNseq:用于扩频的随机码
    %gain:扩频增益
    %phase:用户扩频码相位
    function res = spreadSpectrum(userCode,PNseq,gain,phase)
        %首先对码元进行周期延拓
        [~,userCode2] = selfCopy(userCode,gain);
        %计算扩频码的行数
        [lineSize,~] = size(PNseq);
        %对扩频码进行重排行序,使初相位位于第一行
        PN = PNseq(phase:lineSize,:);
        PN = [PN;PNseq(1:phase-1,:)];
        res = bitMultiple(userCode2,PN(:)');
    end
    

    解扩模块

    deSpreadSpectrum.m

    %本函数用于解扩
    %userCode:需要解扩的用户码元
    %PNseq:用于扩频的随机码
    %gain:扩频增益
    %phase:用户扩频码相位
    function res = deSpreadSpectrum(userCode,PNseq,gain,phase)
        [lineSize,~] = size(PNseq);
        PN = PNseq(phase:lineSize,:);
        PN = [PN;PNseq(1:phase-1,:)];
        temps = bitMultiple(userCode,PN(:)');
        %这里是matlab的一个小bug,重排序以列作为索引,我的要求是以行
        %作为索引,所以要行列反写再取转置矩阵
        temps = reshape(temps,gain,length(temps)/gain);
        temps = temps';
        %解扩第二步,码元判决
        res = ones(1,length(temps(:))/gain);
        for i = 1:length(temps(:))/gain
            if sum(temps(i,:)) < 0
                res(i) = -1;
            end
        end
    end
    

    加扰模块

    scarmbling.m

    %加扰函数
    %source:被加扰的信号
    %PNCode:用于加扰的扰码
    %1:1的数据加扰
    function res = scarmbling(source,PNCode)
        res = bitMultiple(source,PNCode);
    end
    

    去扰模块

    deScarmbling.m

    %本函数用于对信号做去扰处理,实际操作与加扰完全一致
    %input:需要去扰的信号
    %PNseq:用于去扰的随机序列
    function res = deScarmbling(input,PNseq)
        res = bitMultiple(input,PNseq);
    end
    

    调制模块

    modulate.m

    function res = modulate(source,carrier)
    %调制函数
    %source:被调制信号
    %carrier:载波信号
        sizeSource = length(source);
        sizeCarrier = length(carrier);
        res = zeros(sizeSource,sizeCarrier);
        for i = 1:sizeSource
            res(i,:) = double(source(i))*carrier;
        end
        %把res按行拼接成一行
        res = res';
        res = res(:);
    end
    

    解调模块

    demodulate.m

    function res = demodulate(input,carrier)
    %本函数实现对接收信号的解调
    %原理:极性比较
    %input:被解调的信号
    %carrier:载波信号
    
    %按位循环相乘
    res_bitMultiple = bitMultiple(input,carrier);
    %分组相加
    res_arrayGroupSum = arrayGroupSum(res_bitMultiple,length(carrier));
    %{
        以上处理后,结果正负侧近似于泊松分布,为了处理方便,根据大数定理,
        近似地视为正态分布,从而计算阈值。按照正态分布,-1,1,0平分概率,每一个分得1/3的概率。
    %}
    %计算标准差
    res_std = std(res_arrayGroupSum);
    %计算平均数
    res_mean = mean(res_arrayGroupSum);
    %解算阈值
    syms temp;
    %以下计算时会有一个"Unable to solve symbolically. Returning a numeric solution using
    %vpasolve"的警告,让系统不显示
    warning off;
    threshhold_negative = double(solve(normcdf(temp,res_mean,res_std)==1/3));
    %计算概率为2/3时的阈值,也就是判决为1的阈值
    threshhold_postive = double(solve(normcdf(temp,res_mean,res_std)==2/3));
    res = zeros(1,length(res_arrayGroupSum));
    for i = 1:length(res_arrayGroupSum)
        if res_arrayGroupSum(i) > threshhold_postive
            res(i) = 1;
        elseif res_arrayGroupSum(i) < threshhold_negative
            res(i) = -1;
        end
    end
    end
    

    模块测试代码

    本部分的代码用于单独测试三大模块是否正常工作

    扩频解扩模块测试

    testSpreadSpectrum.m

    %本代码用于测试扩频,解扩模块是否正常工作
    %注意扩频与解扩针对的是双极性码
    function testSpreadSpectrum()
        raw = genBipolar(64);
        walshCode = walsh(64);
        afterDSSS = spreadSpectrum(raw,walshCode,4,2);
        res= deSpreadSpectrum(afterDSSS,walshCode,4,2);
        [trueNum,accuracy] = compare(raw,res);
        fprintf("正确码元数量:%d\n正确率:%f\n",trueNum,accuracy); 
    end
    

    加扰去扰模块测试

    testScarmbling.m

    %本代码用于测试加扰,去扰模块能否正常工作
    function testScarmbling()
        %M序列发生器可以自定义阶数和反馈系数
        Mseq = MseqGen(5,67); %产生加扰用的m序列
        raw = tripleGen(1e6);
        afterScarmb = scarmbling(raw,Mseq);
        res = deScarmbling(afterScarmb,Mseq);
        [trueNum,accuracy] = compare(raw,res);
        fprintf("正确码元数量:%d\n正确率:%f\n",trueNum,accuracy);    
    end
    

    调制解调模块测试

    testModulate.m

    %本代码用于测试BPSK调制与解调模块能否正常工作
    function testModulate()
        carrier = 10*sin(0:pi/32:2*pi-pi/32);
        raw = tripleGen(1e6);
        afterModu = modulate(raw,carrier);
        res = demodulate(afterModu,carrier);
        [trueNum,accuracy] = compare(raw,res);
        fprintf("正确码元数量:%d\n正确率:%f\n",trueNum,accuracy);   
    end
    

    非核心代码

    八进制转二进制模块

    Oct2Bin.m

    %八进制转二进制,返回一个二进制数组
    function res = Oct2Bin(value)
        [bitNum,bit] = getPalces(value);
        res = int8(zeros(1,bitNum*3));
        for i = 1:bitNum*3
            bitMain = bit(floor((i-1)/3)+1);
            switch mod(i-1,3)
                case 0
                    if bitMain >= 4
                        res(i) = 1;
                    end
                case 1
                    if bitMain == 2 || bitMain == 3 || bitMain == 6 || bitMain == 7
                       res(i) = 1;
                    end
                case 2
                    if mod(bitMain,2) ~= 0
                        res(i) = 1;
                    end
            end
        end
    end
    

    点乘模块

    bitMultiple.m

    %按bit循环相乘函数,如果信号长度不一致,则较短的信号被循环使用
    %signal1:相乘信号1
    %signal2:相乘信号2
    %res:相乘结果
    function res = bitMultiple(signal_1,signal_2)
        sizeSource = length(signal_1);
        sizePNCode = length(signal_2);
        %如果长度不满足条件时,调换顺序递归调用
        if sizeSource < sizePNCode
            res = bitMultiple(signal_2,signal_1);
            return;
        end
        res = zeros(1,sizeSource);
        for i = 1:sizeSource
            res(i) = signal_1(i) * signal_2(mod(i-1,sizePNCode)+1);
        end
        res = int8(res);
    end
    

    码元比较模块

    compare.m

    %比较两个数组
    %input1:数组1
    %input2:数组2
    %res:正确码元数量
    %accuracy:正确率
    function [res,accuracy] = compare(input1,input2)
        temp = (input1 == input2);
        res = length(find(temp == 1));
        sizeInput = max(length(input1),length(input2));
        accuracy = res/double(sizeInput);
    end
    

    双极性码生成模块

    genBipolar.m

    %产生双极性码
    %num:双极性码的规模
    %res:满载双极性码的数组
    function res = genBipolar(num)
        res = rand(1,num);
        res = value2Bipolar(res);
    end
    

    数字位数获取模块

    getPlaces.m

    %统计一个数字的位数,并返回每位的数字
    function [Places,item] = getPalces(value)
        Places = 0;
        temp = abs(value);
        while temp ~= 0
            temp = floor(temp/10);
            Places = Places + 1;
        end
        item = uint8(zeros(1,Places));
        temp = value;
        for i = Places:-1:1
            item(i) = mod(temp,10);
            temp = floor(temp/10);
        end
    end
    

    功率计算模块

    powerCnt.m

    %计算输入信号的平均功率(dBW)
    function res = powerCnt(input)
        res = 10*log10(sum(input.*input));
    end
    

    周期延拓模块

    selfCopy.m

    %本函数实现数组的周期延拓
    %input:需要延拓的数组
    %times-1:延拓的次数
    %比如selfCopy([1,2,3],2) = [1,2,3,1,2,3,1,2,3]
    function [res,res2] = selfCopy(input,times)
        if times <= 1
            res = input;
        else
            res = zeros(length(input),times);
            for i = 1:times
                res(:,i) = input;
            end
            res2 = res';
            res2 = res2(:)';
            res = res(:)';
        end
    end
    

    三极码生成模块

    tripleGen.m

    %本函数用于生成指定数量的随机三极性码,主要用于做模块测试
    %num:数量
    %res:满载结果的数组
    function res = tripleGen(num)
        raw = rand(1,num);
        for i = 1:num
            if raw(i) >= 0.75
                raw(i) = 1;
            elseif raw(i) <= 0.25
                raw(i) = -1;
            else
                raw(i) = 0;
            end
        end
        res = int8(raw);
    end
    

    0~1转双极性模块

    value2Bipolar.m

    % 本函数用户把随机生成的0~1之间的double数转换成双极性码
    function res = value2Bipolar(input)
        res = zeros(1,length(input));
        for index = 1:length(input)
            if(input(index) < 0.5)
                res(index) = -1;
            else
                res(index) = 1;
            end
        end
        res = int8(res);
    end
    

    分组相加模块

    arrayGroupSum.m

    function res = arrayGroupSum(input,group_num)
    %arrayGroupSum 数组分组求和,如果数组长度除去group_num无法整除,则截短input数组
    %input 目标数组
    %group_num 分组数
    len = floor(length(input)/group_num);
    res = zeros(1,len);
    for i = 1:len
        res(i) = sum(input((i-1)*group_num+1:i*group_num));
    end
    end
    
    展开全文
  • Matlab的各校ppt历年题目及获奖论文-美赛专题3.rar ppt包括清华大学、浙江大学、国防科技大学、纽约大学 论文主要是全国的,还有地区的学校的,以及全美的。共334M
  • MATLAB与仿真练习 实验1 橡皮球从一个高度为的高处以初速度下落到地面其高度h速度v与时间t的关系由下式给出 (1) (2) 其中为重力加速度-9.81m/s2用matlab程序编写t从0到500以1为间隔并绘出图像应由键盘输入 实验2 一...
  • 题目 1 已知系统方框图 12s 4 s 6 其中 G (s) G (s) 1 2 2 2 H (s) 1 s 5s 4 s 6s 2 求利用 MATLAB 建立闭环控制系统的传递函数 要求程序代码以 M 文件保存同时规定结果输出只有传递函数 1 题目 2 已知单位负反馈...
  • M 文件等 一填空题 1MATLAB常用操作界面包括命令窗口工作空间窗口浏览器 历史命令窗口当前目 录窗口内存数组编辑器 M 文件编辑 / 调试器 帮助导航 / 浏览器图形窗口等 2MATLAB中 Inf 或 inf 表示无穷大 NaN 或 nan ...
  • Matlab的各校ppt历年题目及获奖论文-建模题目及论文5.rar ppt包括清华大学、浙江大学、国防科技大学、纽约大学 论文主要是全国的,还有地区的学校的,以及全美的。共334M
  • Matlab的各校ppt历年题目及获奖论文-建模题目及论文6.rar ppt包括清华大学、浙江大学、国防科技大学、纽约大学 论文主要是全国的,还有地区的学校的,以及全美的。共334M
  • 内含茎叶图、累积频数图、频数、频率输出函数文件、卡方分布文件、经验函数图等文件的代码,附有注释
  • 电子信息工程专业课程设计任务书 学生 电信1 专业班级 电信 1 学号 班 题目 M序列产生器的MATLAB设计与实现 课题性质 工程技术研究 课题来源 自拟课题 指导教师 同组 无 主要容 了解m序列的产生输出及其自相关序列观...
  • Matlab的各校ppt历年题目及获奖论文-建模题目及论文4.rar ppt包括清华大学、浙江大学、国防科技大学、纽约大学 论文主要是全国的,还有地区的学校的,以及全美的。共334M
  • 图像亮(灰)度变换采用MATLAB工具箱中的亮度变换函数、直方图处理函数等函数及其相应的语法格式对实验一生成的图像进行处理;空间滤波采用MATLAB工具箱中的标准(线性和非线性)空间滤波器对图像进行空间滤波处理...

    目 录

    实验一、数字图像获取和格式转换 2

    实验二、图像亮度变换和空间滤波 6

    实验三、频域处理 7

    实验四、图像复原 9

    实验五、彩色图像处理 10

    实验六、图像压缩 11

    实验七、图像分割 13

    教材与参考文献 14

    实验一、数字图像获取和格式转换

    一、 实验目的

    1掌握使用扫描仪、数码相机、数码摄像级机、电脑摄像头等数字化设备以及计算机获取数字图像的方法;

    2修改图像的存储格式;并比较不同压缩格式图像的数据量的大小。

    二、 实验原理

      数字图像获取设备的主要性能指标有x、y方向的分辨率、色彩分辨率(色彩位数)、扫描幅面和接口方式等。各类设备都标明了它的光学分辨率和最大分辨率。分辨率的单位是dpi,dpi是英文Dot Per Inch的缩写,意思是每英寸的像素点数。

    扫描仪扫描图像的步骤是:首先将欲扫描的原稿正面朝下铺在扫描仪的玻璃板上,原稿可以是文字稿件或者图纸照片;然后启动扫描仪驱动程序后,安装在扫描仪内部的可移动光源开始扫描原稿。为了均匀照亮稿件,扫描仪光源为长条形,并沿y方向扫过整个原稿;照射到原稿上的光线经反射后穿过一个很窄的缝隙,形成沿x方向的光带,又经过一组反光镜,由光学透镜聚焦并进入分光镜,经过棱镜和红绿蓝三色滤色镜得到的RGB三条彩色光带分别照到各自的CCD上,CCD将RGB光带转变为模拟电子信号,此信号又被A/D变换器转变为数字电子信号。至此,反映原稿图像的光信号转变为计算机能够接受的二进制数字电子信号,最后通过串行或者并行等接口送至计算机。扫描仪每扫一行就得到原稿x方向一行的图像信息,随着沿y方向的移动,在计算机内部逐步形成原稿的全图。扫描仪工作原理见图1.1。


    v2-3d51a4b07881a17b02c9899a9dc3bb75_b.jpg


    图1.1扫描仪的工作原理

    在扫描仪的工作过程中,有两个元件起到了关键的作用。一个是CCD,它将光信号转换成为电信号;另一个是A/D变换器,它将模拟电信号变为数字电信号。CCD是Charge Couple Device的缩写,称为电荷耦合器件,它是利用微电子技术制成的表面光电器件,可以实现光电转换功能。CCD在摄像机、数码相机和扫描仪中应用广泛,只不过摄像机中使用的是点阵CCD,即包括x、y两个方向用于摄取平面图像,而扫描仪中使用的是线性CCD,它只有x一个方向,y方向扫描由扫描仪的机械装置来完成。CCD芯片上有许多光敏单元,它们可以将不同的光线转换成不同的电荷,从而形成对应原稿光图像的电荷图像。

    数码相机的系统结构(见图1.2)数码相机的许多特殊部件,如图像传感器(CCD或CMOS)、模/数转换器(A/D)、数字信号处理单元(DSP)、图像存储器、液晶显示器(LCD)以及输出控制单元(连接端口)等是传统胶片相机所没有的。
    仔细分析一下数码相机的原理方框图,我们不难发现,数码相机的系统工作过程就是把光信号转化为数字信号的过程。数码相机使用CCD电荷耦合器件这种光敏元件代代替胶卷感光成像。光线通过透镜系统和滤色器(滤光器)投射到CCD光敏元件上,CCD元件将其光强和色彩转换为电信号记录到数码相机的存储器中,形成计算机可以处理的数字信号。
    数码相机除了光学透镜系统外,其余几乎全由电子电路控制。基本的信号处理过程非常简单。由CCD送来的电信号通过A/D转换器转换为数字信号,然后送入具有信号处理能力的DSP(数字信号处理器)。DSP处理工作量很大,一般都设计成专用的硬件。信号进一步送给离散余弦变换部件DCT进行JPEG压缩,然后通过接口电路记录到位于最后一级的存储器。


    v2-e1de637847ee0ee1782bbc89f2e55d96_b.jpg


    图1.2 数码相机原理图

      数码摄像机的感光器件也即数码摄像机感光成像的部件,能把光线转变成电荷,通过模数转换器芯片转换成数字信号。目前数码摄像机的核心成像部件有两种:一种是广泛使用的CCD(电荷藕合)元件;另一种是CMOS(互补金属氧化物导体)器件。电荷藕合器件图像传感器CCD(Charge Coupled Device),它使用一种高感光度的半导体材料制成,能把光线转变成电荷,通过模数转换器芯片转换成数字信号,数字信号经过压缩以后由相机内部的闪速存储器或内置硬盘卡保存,因而可以轻而易举地把数据传输给计算机,并借助于计算机的处理手段,根据需要和想像来修改图像。CCD由许多感光单位组成,通常以百万像素为单位。当CCD表面受到光线照射时,每个感光单位会将电荷反映在组件上,所有的感光单位所产生的信号加在一起,就构成了一幅完整的画面。互补性氧化金属半导体CMOS(Complementary Metal-Oxide Semiconductor)和CCD一样同为在数码相机中可记录光线变化的半导体。CMOS的制造技术和一般计算机芯片没什么差别,主要是利用硅和锗这两种元素所做成的半导体,使其在CMOS上共存着带N(带–电) 和 P(带+电)级的半导体,这两个互补效应所产生的电流即可被处理芯片纪录和解读成影像。然而,CMOS的缺点就是太容易出现杂点, 这主要是因为早期的设计使CMOS在处理快速变化的影像时,由于电流变化过于频繁而会产生过热的现象。由两种感光器件的工作原理可以看出,CCD的优势在于成像质量好,但是由于制造工艺复杂,只有少数的厂商能够掌握,所以导致制造成本居高不下,特别是大型CCD,价格非常高昂。在相同分辨率下,CMOS价格比CCD便宜,但是CMOS器件产生的图像质量相比CCD来说要低一些。到目前为止,市面上绝大多数的消费级别以及高端数码相机都使用CCD作为感应器;CMOS感应器则作为低端产品应用于一些摄像头上,是否具有CCD感应器变成了人们判断数码相机档次的标准之一。

    1. 实验步骤

    1扫描仪、数码相机(手机)、数码摄像机或电子摄像头通过数据线与计算机的连接;

    2打开计算机,安装外部设备的驱动程序;

    3将数字图像获取设备中的图像复制进计算机,保存;

    4调整彩色图像的色彩;

    5将获得的图像的格式分别转换为“*.gif”、“*.tif”、“*.jpg”的格式保存,检查图像文件数据量的大小。将图片保存或拷贝到MATLAB程序组根目录的“work”文件夹中,以便后面的实验做为“原图像”利用。

    6记录和整理实验报告。


    1. 实验仪器

    1计算机;

    2扫描仪(或数码相机、数字摄像机等)及其驱动程序盘;

    3图像处理软件(画图,Photoshop, Microsoft photo edit等);

    4记录用的笔、纸。


    1. 实验报告内容

    1叙述操作过程

    2提交用扫描仪扫描得到的图像。


    1. 思考题

    1试述数字图像获取设备的工作原理。

    2你使用过图像获取设备有哪些。



    实验二、图像亮(灰)度变换与空间滤波

    1. 实验目的

    1了解图像亮(灰)度变换与空间滤波的意义和手段;

    2熟悉图像亮(灰)度变换与空间滤波的MATLAB函数和语法;

    3熟练掌握应用MATLAB软件编程进行图像亮(灰)度变换与空间滤波的方法;

    4参照课本和课堂教学的例题对图像进行图像亮(灰)度变换与空间滤波。


    1. 实验原理

    图像亮(灰)度变换与空间滤波属于在空间域内处理图像,是直接对图像的像素进行处理。有两种重要的空间域处理方法,即亮度(或灰度级)变换与空间滤波,后一种方法有时称为邻域处理或空间卷积。

    图像亮(灰)度变换采用MATLAB工具箱中的亮度变换函数、直方图处理函数等函数及其相应的语法格式对实验一生成的图像进行处理;空间滤波采用MATLAB工具箱中的标准(线性和非线性)空间滤波器对图像进行空间滤波处理。


    1. 实验步骤

    1打开计算机,安装和启动MATLAB程序;程序组中“work”文件夹中应有待处理的图像文件;

    2利用MatLab工具箱中的函数、语法,参照课本和课堂讲解的例题对图像进行图像亮(灰)度变换与空间滤波,并显示获得的图像;

    3记录和整理实验报告。


    1. 实验仪器

    1计算机;

    2 MATLAB程序;

    3移动式存储器(软盘、U盘等)。

    4记录用的笔、纸。


    1. 实验报告内容

    1叙述实验过程;

    2提交实验的原始图像和结果图像。


    1. 思考题

    1.MATLAB程序的IPT中有哪些图像亮(灰)度变换函数?写出函数的语法。

    2.图像亮(灰)度变换与空间滤波有什么不同?




    实验三、频域处理

    实验目的

    1了解图像频域处理的意义和手段;

    2熟悉离散傅里叶变换的基本性质;

    3熟练掌握图像傅里叶变换的方法及应用;

    4通过实验了解二维频谱的分布特点;

    5通过本实验掌握利用MATLAB的工具箱实现数字图像的频域处理。


    1. 实验原理

    傅里叶变换是线性系统分析的一个有力工具,它能够定量地分析诸如数字化系统、采样点、电子放大器、卷积滤波器、噪音和显示点等的作用。通过实验培养这项技能,将有助于解决大多数图像处理问题。对任何想在工作中有效应用数字图像处理技术的人来说,把时间用在学习和掌握博里叶变换上是很有必要的。

    2图像变换的基本原理

    (1)傅立叶(Fourier)变换的定义

    对于二维信号,二维Fourier变换定义为:

    v2-cc580480250b03f9c7fd44c203180ecd_b.jpg


      二维离散傅立叶变换为:

    v2-61e10f172b32a49f4135403545787c8f_b.jpg


      图像的傅立叶变换与一维信号的傅立叶变换变换一样,有快速算法。实际上,现在有实现傅立叶变换的芯片,可以实时实现傅立叶变换。


    1. 实验步骤

    1打开计算机,启动MATLAB程序;程序组中“work”文件夹中应有待处理的图像文件;

    2调入“实验一”中获取的数字图像,应用IPT函数(参照例题)进行图像频域处理;

    3显示原图像与频域处理后的图像及频谱图。

    4记录和整理实验报告


    1. 实验仪器

    1计算机;

    2 MATLAB程序;

    3移动式存储器(软盘、U盘等)。

    4记录用的笔、纸。


    1. 实验报告内容

    1叙述实验过程;

    2提交实验的原始图像和结果图像。


    1. 思考题

    1.叙述对数字图像进行DFT处理的原理。
      2.通过对图像进行频域处理可以使图像产生什么样的变化?

    3.如何从空间滤波器获得频域滤波器?

    4.如何在频域中直接生成频域滤波器


    实验四、图像复原

    1. 实验目的

    1、了解图像复原的原理;

    2、掌握常用图像复原方法。


    1. 实验原理
    1. 分析不同条件下图像退化成因和处理方法;
    2. 根据退化的数学模型对退化图像进行处理,复原原始图像。





    1. 实验步骤

    1打开计算机,启动MATLAB程序;

    2调入“实验一”中获取的数字图像,应用IPT的函数对图像作模糊化和添加噪声处理;

    3 参照课本和课堂讲解的例题中的方法对退化的图像进行复原。

    4记录和整理实验报告


    1. 实验仪器

    1计算机;

    2 MATLAB(含IPT)等程序;

    3移动式存储器(软盘、U盘等)。

    4记录用的笔、纸。


    1. 实验报告内容

    1叙述实验过程;

    2提交实验的原始图像、退化图像和复原图像。


    1. 思考题

    1.常见的图像退化模型有哪些种类?
      2.不同的PSF对复原效果有什么影响?


    实验五、彩色图像处理

    一、实验目的

    1、了解彩色空间的基本概念及转换原理;

    2、熟悉MATLAB中彩色图像的表示方法;

    3、使用MatLab函数实现各类彩色空间的转换;

    4、使用MatLab函数实现各种图像类型的转换;


    二、实验原理

    (1)利用MATLAB的IPT进行彩色图像的读、写和显示;

    (2)颜色空间的基本概念;

    (3)颜色空间包括某个颜色域的所有颜色,实验中采用的颜色模型有NTSC、HSV、YcbCr模型等。各种颜色空间在图像处理中各有优势,可以互相转换;


    三、实验步骤

    1打开计算机,启动MATLAB程序;

    2调入“实验一”中获取的数字图像,采用IPT的各种颜色空间转换函数进行图像读取、显示,并显示各分量图像。

    3 试根据转换公式,自行编制其他颜色空间转换函数

    4. 记录和整理实验报告



    四、实验仪器

    1计算机;

    2 MATLAB等程序;

    3移动式存储器(软盘、U盘等)。

    4记录用的笔、纸。



    五、实验报告内容

    1叙述实验过程;

    2提交实验的原始图像和结果图像。


    六、思考题

    比较不同颜色空间的差别。


    实验六、图像压缩

    1. 实验目的
      1. 理解有损压缩和无损压缩的概念;
      2. 理解图像压缩的主要原则和目的; 
      3. 了解几种常用的图像压缩编码方式。
      4. 利用MATLAB程序进行图像压缩。



    1. 实验原理

    1.图像压缩原理

    图像压缩主要目的是为了节省存储空间,增加传输速度。图像压缩的理想标准是信息丢失最少,压缩比例最大。不损失图像质量的压缩称为无损压缩,无损压缩不可能达到很高的压缩比;损失图像质量的压缩称为有损压缩,高的压缩比是以牺牲图像质量为代价的。压缩的实现方法是对图像重新进行编码,希望用更少的数据表示图像。

    信息的冗余量有许多种,如空间冗余,时间冗余,结构冗余,知识冗余,视觉冗余等,数据压缩实质上是减少这些冗余量。高效编码的主要方法是尽可能去除图像中的冗余成分,从而以最小的码元包含最大的图像信息。

    编码压缩方法有许多种,从不同的角度出发有不同的分类方法,从信息论角度出发可分为两大类。

    (1).冗余度压缩方法,也称无损压缩、信息保持编码或熵编码。具体说就是解码图像和压缩编码前的图像严格相同,没有失真,从数学上讲是一种可逆运算。

    (2)信息量压缩方法,也称有损压缩、失真度编码或熵压缩编码。也就是说解码图像和原始图像是有差别的,允许有一定的失真。

    应用在多媒体中的图像压缩编码方法,从压缩编码算法原理上可以分为以下3类:

    (1)无损压缩编码种类

    哈夫曼(Huffman)编码,算术编码,行程(RLE)编码,Lempel zev编码。

    (2)有损压缩编码种类

    预测编码,DPCM,运动补偿;

    频率域方法:正交变换编码(如DCT),子带编码;

    空间域方法:统计分块编码;

    模型方法:分形编码,模型基编码;

    基于重要性:滤波,子采样,比特分配,向量量化;

    (3)混合编码。

    有JBIG,H261,JPEG,MPEG等技术标准。

    本实验主要利用MATLAB程序进行Huffman编码、算术编码、离散余弦变换(DCT)和行程编码(Run Length Encoding, RLE)。



    1. 实验步骤

    1打开计算机,启动MATLAB程序;

    2调入“实验一”中获取的数字图像,并进行数据的Huffman编码、算术编码、DCT、游程编码等压缩处理;

    3 将原图像在Photoshop软件中打开,分别以不同的位图文件格式进行“另保存”,比较它们的数据量。

    4记录和整理实验报告


    1. 实验仪器

    1计算机;

    2 MATLAB、Photoshop等程序;

    3移动式存储器(软盘、U盘等)。

    4记录用的笔、纸。


    1. 实验报告内容

    1叙述实验过程;

    2提交实验的原始图像和结果图像。


    1. 思考题

    1.图像中哪些信息是主要的,哪些信息是次要的?
      2.简述离散余弦变换(DCT)和行程编码(RLE)的原理。





    实验七、图像分割


    1. 实验目的

    1、通过实验体会一些主要的分割算子对图像处理的效果,以及各种因素对分割效果的影响;

    2、使用MatLab 软件进行图像的分割;

    3、能够评价各主要算子在无噪声条件下和噪声条件下的分割性能;

    4、能够掌握分割条件(阈值等)的选择;

    5、完成规定图像的处理并要求正确评价处理结果,能够从理论上作出合理的解释。


    二、实验原理

    1.使用Roberts 算子的图像分割实验,调入并显示一幅图像*.gif或*.tif;使用Roberts 算子对图像进行边缘检测处理;

    2.使用Prewitt 算子的图像分割实验

    使用Prewitt 算子进行内容(1)中的全部步骤。

    3.使用Sobel 算子的图像分割实验,使用Sobel 算子进行内容(1)中的全部步骤。

    4.使用LoG (拉普拉斯-高斯)算子的进行图像分割实验。

    5.使用Canny算子的进行图像分割实验。



    三、实验步骤

    1打开计算机,启动MATLAB程序;

    2调入“实验一”中获取的数字图像,并进行图像分割处理;

    3记录和整理实验报告



    四、实验仪器

    1计算机;

    2 MATLAB等程序;

    3移动式存储器(软盘、U盘等)。

    4记录用的笔、纸。



    五、实验报告内容

    1叙述实验过程;

    2提交实验的原始图像和结果图像。


    六、思考题

    1. 评价一下Roberts 算子、Prewitt 算子、Sobel 算子对于噪声条件下边界检测的性能。

    2. 为什么LoG梯度检测算子的处理结果不需要象Prewitt 等算子那样进行幅度组合?

    3. 实验中所使用的四种算子所得到的边界有什么异同?


    教材

    ㈠教材

    [1].(美)Rafael C. Gonzalez , Richard E. Woods, Steven L. Eddins. Digital Image Processing Using MATLAB.数字图像处理(MATLAB版)[M].阮秋琦 等. 北京:电子工业出版社,2005.9

    展开全文
  • Matlab的各校ppt历年题目及获奖论文-数学建模及论文7.rar ppt包括清华大学、浙江大学、国防科技大学、纽约大学 论文主要是全国的,还有地区的学校的,以及全美的。共334M
  • MATLAB期末考试试卷及其参考答案 一填空题每空 1 分 20 分 1MATLAB 常用操作界面包括 工作空间窗口 内存数组编辑器 M 文件 编辑 /调试器帮助导航 /浏览器图形窗口等 2MATLAB 中 Inf 或 inf 表示 NaN 或 nan表示 ...
  • Matplotlib是Python最著名的绘图库之一,提供了一整套和MATLAB相似的命令API,既适合交互式地进行制图,也可以作为绘图控件方便地嵌入到GUI应用程序中 python -m pip install Matplotlib 三:使用IDLE打开和执行...

    (还在更新中…) 这篇博客花费了我的大量时间和精力,从创作到维护;若认可本篇博客,希望给一个点赞、收藏

    并且,遇到了什么问题,请在评论区留言,我会及时回复的


    这本书对Python的知识点的描述很详细,而且排版看的很舒服

    1. 几个例题: 假装自己从零开始学,将一些有代表性、有意思的例题抽取出来
    2. 部分复习题: 遇到有意思的复习题,我会拿出来,并且进行分析
    3. 上机实践: 全部上机实践题的解题思路

    文章目录

    第一章 Python概述


    几个例题

    一:Python3.7.4下载

    python3.7.4下载地址:https://www.python.org/downloads/release/python-374/
    页面最下面:

    下载,安装完python后:出现的四个玩意:Python 3.7 Module Docs,IDLE,Python 3.7 Manuals,Python 3.7(64-bit)

    1. Python 3.7 Module Docs(64-bit)
      点击之后,会出现一个网页(将我下载的Python3.7.4文件夹中包含的模块都列了出来,页面不止这么点,还可以往下拉)

    2. IDLE(Python 3.7 64-bit)
      一个Python编辑器,Python内置的集成开发工具

    3. Python 3.7 Manuals(64-bit)
      Python 3.7 开发手册

    4. Python 3.7(64-bit)
      控制台中运行Python

    二:更新pip和setuptools包,安装NumPy包,安装Matplotlib包

    以下三个命令都是在控制台(windows中的cmd)中运行

    更新pip和setuptools包

    1. pip用于安装和管理Python扩展包
    2. setuptools用于发布Python包
    python -m pip install -U pip setuptools
    

    安装NumPy

    Python扩展模块NumPy提供了数组和矩阵处理,以及傅立叶变换等高效的数值处理功能

     python -m pip install NumPy
    

    安装Matplotlib包

    Matplotlib是Python最著名的绘图库之一,提供了一整套和MATLAB相似的命令API,既适合交互式地进行制图,也可以作为绘图控件方便地嵌入到GUI应用程序中

    python -m pip install Matplotlib
    

    三:使用IDLE打开和执行Python源文件程序

    首先:
    有一个.py文件test.py
    在这里插入图片描述

    使用IDLE打开.py文件的两种方式:

    1. 右键test.py---->Edit With IDLE---->Edit With IDLE 3.7(64-bit)
    2. 打开IDLE,然后File---->Open(或者ctrl+O)选择.py文件

    运行

    Run---->Run Module(或者F5
    就会出现这个界面,执行结果显示在这个界面中

    补充一点:
    如果在IDLE中编辑.py文件,记得修改后要保存(ctrl+s),再运行(F5

    四:使用资源管理器运行hello.py

    hello.py文件在桌面

    import random
    
    print("hello,Python")
    print("你今天的随机数字是:",random.choice(range(10)))#输出在0-9之间随机选择的整数
    input()
    
    1. 在桌面打开PowerShell(还有两种输入方式:python hello.py或者.\hello.py
    2. 或者在桌面打开cmd, 就输入hello.py或者python hello.py

    补充:上述两种命令中的hello.py都是相对路径,因为文件在桌面,而且我是在桌面打开cmd,所以文件路劲可以这么简简单单的写。如果文件存储位置和cmd打开位置不一样,请使用绝对路径

    五:命令行参数示例hello_argv.py

    hello_argv.py文件在桌面

    import sys
    
    print("Hello,",sys.argv[1])
    #这样写也行:
    #print("Hello,"+sys.argv[1])
    
    1. 在桌面打开PowerShell(还有两种输入方式:python hello_argv.py 任意输入或者./hello_argv.py 任意输入
    2. 或者在桌面打开cmd,就输入hello_argv.py 任意输入或者python hello_argv.py 任意输入

    补充:以图中第一个命令举例,hello_argv.pysys.argv[0]Pythonsys.argv[1]

    第二章 Python语言基础


    选择题:1、3、7、8

    1. 在Python中,以下标识符合法的是

    A. _B. 3CC. it’sB. str

    答案:A

    1. 标识符的第一个字符必须是字母,下划线(_);其后的字符可以是字母、下划线或数字。
    2. 一些特殊的名称,作为python语言的保留关键字,不能作为标识符
    3. 以双下划线开始和结束的名称通常具有特殊的含义。例如__init__为类的构造函数,一般应避免使用

    B:以数字开头,错误
    C:使用了',不是字母、下划线或数字
    D:str是保留关键字

    3. 在下列Python语句中非法的是

    A. x = y =1B. x = (y =1)C. x,y = y,xB. x=1;y=1

    答案:B,C

    7. 为了给整型变量x,y,z赋初值10,下面Python赋值语句正确的是

    A. xyz=10B. x=10 y=10 z=10C. x=y=z=10B. x=10,y=10,z=10

    答案:C

    1. 分号;用于在一行书写多个语句
    2. python支持链式赋值

    A:赋值对象是xyz
    B:分号;用于在一行书写多个语句,而不是' '(即空格)
    D:分号;用于在一行书写多个语句,而不是,

    8. 为了给整型变量x,y,z赋初值5,下面Python赋值语句正确的是

    A. x=5;y=5;z=5B. xyz=5C. x,y,z=10B. x=10,y=10,z=10

    答案:A

    Pytho能支持序列解包赋值,但是变量的个数必须与序列的元素个数一致,否则会报错

    B:赋值对象是xyz
    C:序列解包赋值,变量的个数必须与序列的元素个数一致,否则会报错
    D:分号;用于在一行书写多个语句,而不是,

    思考题:9

    9.下列Python语句的输出结果是

    def f():pass
    print(type(f()))
    

    结果:<class 'NoneType'>

    NoneType数据类型包含唯一值None,主要用于表示空值,如没有返回值的函数的结果

    上机实践:2~6

    2. 编写程序,输入本金、年利率和年数,计算复利(结果保留两位小数)

    money = int(input("请输入本金:"))
    rate = float(input("请输入年利率:"))
    years = int(input("请输入年数:"))
    amount = money*((1+rate/100)**years)
    print(str.format("本金利率和为:{0:2.2f}",amount))
    

    运行:

    请输入本金:1000
    请输入年利率:6.6
    请输入年数:10
    本金利率和为:1894.84
    

    3. 编写程序,输入球的半径,计算球的表面积和体积(结果保留两位小数)

    import math
    r = float(input("请输入球的半径:"))
    area = 4 * math.pi * r**2
    volume = 4/3*math.pi*r**3
    print(str.format("球的表面积为:{0:2.2f},体积为:{1:2.2f}",area,volume))
    

    运行:

    请输入球的半径:666
    球的表面积为:5573889.08,体积为:1237403376.70
    

    4. 编写程序,声明函数getValue(b,r,n),根据本金b,年利率r和年数n计算最终收益v

    money = int(input("请输入本金:"))
    rate = float(input("请输入年利率(<1):"))
    years = int(input("请输入年数:"))
    
    def getValue(b,r,n):
        return b*(1+r)**n
    
    print(str.format("本金利率和为:{0:2.2f}",getValue(money,rate,years)))
    

    运行:

    请输入本金:10000
    请输入年利率(<1):0.6
    请输入年数:6
    本金利率和为:167772.16
    

    5. 编写程序,求解一元二次方程x2-10x+16=0

    from math import sqrt 
    x = (10+sqrt(10*10-4*16))/2
    y = (10-sqrt(10*10-4*16))/2
    print(str.format("x*x-10*x+16=0的解为:{0:2.2f},{1:2.2f}",x,y))
    

    运行:

    x*x-10*x+16=0的解为:8.00,2.00
    

    6. 编写程序,提示输入姓名和出生年份,输出姓名和年龄

    import datetime
    sName = str(input("请输入您的姓名:"))
    birthday = int(input("请输入您的出生年份:"))
    age = datetime.date.today().year - birthday
    print("您好!{0}。您{1}岁。".format(sName,age))
    

    运行:

    请输入您的姓名:zgh
    请输入您的出生年份:1999
    您好!zgh。您20岁。
    

    案例研究:使用Pillow库处理图像文件

    https://blog.csdn.net/Zhangguohao666/article/details/102060722

    通过此案例,进一步了解Python的基本概念:模块、对象、方法和函数的使用

    第三章 程序流程控制


    几个例题

    一:编程判断某一年是否为闰年

    闰年:年份能被4整除但不能被100整除,或者可以被400整除。
    口诀:四年一闰,百年不闰,四百必闰

    代码一:

    y = int(input("请输入要判断的年份:"))
    if((y % 4 == 0 and y % 100 != 0) or y % 400 == 0):
        print("是闰年")
    else:
        print("不是闰年")
    

    代码二(使用calendar模块的isleap()函数来判断):

    from calendar import isleap
    
    y = int(input("请输入要判断的年份:"))
    if(isleap(y)):print("闰年")
    else:print("不是闰年")
    

    二:利用嵌套循环打印九九乘法表

    九九乘法表:

    for i in range(1,10):
        s = ""
        for j in range(1,10):
            s += str.format("%d * %d = %02d  " %(i, j, i*j))
        print(s)
    

    下三角:

    for i in range(1,10):
        s = ""
        for j in range(1,i+1):
            s += str.format("%d * %d = %02d  " %(i, j, i*j))
        print(s)
    

    上三角:

    for i in range(1,10):
        s = ""
        for k in range(1,i):
            s += "                   "
        for j in range(i,10):
            s += str.format("%d * %d = %02d  " %(i, j, i*j))
        print(s)
    

    三:enumerate()函数和下标元素循环示例

    Python语言中的for循环直接迭代对象集合中的元素,如果需要在循环中使用索引下标访问集合元素,则可以使用内置的enumerate()函数

    enumerate()函数用于将一个可遍历的数据对象(例如列表、元组或字符串)组合为一个索引序列,并返回一个可迭代对象,故在for循环当中可直接迭代下标和元素

    seasons = ["Spring","Summer","Autumn","Winter"]
    for i,s in enumerate(seasons,start=1):    #start默认从0开始
        print("第{0}个季节:{1}".format(i,s))
    

    运行:

    第1个季节:Spring
    第2个季节:Summer
    第3个季节:Autumn
    第4个季节:Winter
    

    四:zip()函数和并行循环示例

    如果需要并行遍历多个可迭代对象,则可以使用Python的内置函数zip()

    zip()函数将多个可迭代对象中对应的元素打包成一个个元组,然后返回一个可迭代对象。如果元素的个数不一致,则返回列表的长度与最短的对象相同。

    利用运算符*还可以实现将元组解压为列表

    evens = [0,2,4,6,8]
    odds = [1,3,5,7,9]
    for e,o in zip(evens,odds):
        print("{0} * {1} = {2}".format(e,o,e*o))
    

    运行:

    0 * 1 = 0
    2 * 3 = 6
    4 * 5 = 20
    6 * 7 = 42
    8 * 9 = 72
    

    五:map()函数和循环示例

    如果需要遍历可迭代对象,并使用指定函数处理对应的元素,则可以使用Python的内置函数map()

    map(func,seq1[,seq2,...])
    
    • func作用于seq中的每一个元素,并将所有的调用结果作为可迭代对象返回。
    • 如果func为None,该函数的作用等同于zip()函数

    计算绝对值:

    >>> list(map(abs, [-1, 0, 7, -8]))
    [1, 0, 7, 8]
    

    计算乘幂:

    >>> list(map(pow, range(5), range(5)))
    [1, 1, 4, 27, 256]
    

    计算ASCII码:

    >>> list(map(ord, 'zgh'))
    [122, 103, 104]
    

    字符串拼接(使用了匿名函数lambda):

    >>> list(map(lambda x, y: x+y, 'zgh', '666'))
    ['z6', 'g6', 'h6']
    

    选择题:1、2、3

    1. 下面的Python循环体的执行次数与其他不同的是

    A.

    i = 0						
    while(i <= 10):
    	print(i)
    	i = i + 1
    

    B.

    i = 10
    while(i > 0):
    	print(i)
    	i = i - 1
    

    C.

    for i in range(10):
    	print(i)
    

    D.

    for i in range(10,0,-1):
    	print(i)
    

    答案:A

    A:[0,10] 执行11次
    B:[10,1] 执行10次
    C:[0,9) 执行10次
    D:[10,0) 执行10次

    2. 执行下列Python语句将产生的结果是

    x = 2; y = 2.0
    if(x == y): print("Equal")
    else: print("Not Equal")
    
    A. EqualB. Not EqualC. 编译错误D. 运行时错误

    答案:A

    Python中的自动类型转换:

    1. 自动类型转换注意针对Number数据类型来说的
    2. 当2个不同类型的数据进行运算的时候,默认向更高精度转换
    3. 数据类型精度从低到高:bool int float complex
    4. 关于bool类型的两个值:True 转化成整型是1;False 转化成整型是0

    int类型的2转化为float类型的2.0

    3. 执行下列Python语句将产生的结果是

    i= 1 	
    if(i): print(True) 	
    else: print(False)
    
    A. 输出1B. 输出TrueC. 输出FalseD. 编译错误

    答案:B

    在Python中,条件表达式最后被评价为bool值True或False。

    如果表达式的结果为数值类型(0),空字符串(""),空元组(()),空列表([]),空字典({}),其bool值为False,否则其bool值为True

    填空题:6

    6. 要使语句for i in range(_,-4,-2)循环执行15次,则循环变量i的初值应当为

    答案:26或者25

    一开始我给的答案是26,经过评论区 的提醒:
    在这里插入图片描述

    >>> a = 0
    >>> for i in range(26, -4, -2): a+=1
    
    >>> print(a)
    15
    
    >>> a = 0
    >>> for i in range(25, -4, -2): a+=1
    
    >>> print(a)
    15
    

    这种题目有一个规律:for i in range(x,y,z):
    若循环中没有break或者continue语句,
    执行次数的绝对值:result = (x-y)÷z

    但实际上没有这么简单:

    • 如果步长为 -1或者1,那么答案只有一个
    • 如果步长为 -2或者2,那么答案有两个
    • 如果步长为 -3或者3,那么答案有三个

    通过公式算出 x 之后,

    • 如果步长为2,还要计算 (x ± 1) - z × (result-1) 的值,然后再经过琐碎的判断即可
    • 如果步长为3,还要计算 (x ± 2) - z × (result-1) 的值,…

    虽然看着麻烦,但实际上是很好理解的

    思考题:3~6

    3. 阅读下面的Python程序,请问程序的功能是什么?

    from math import sqrt
    
    n = 0
    for m in range(101,201,2):
        k = int(sqrt(m))
        for i in range(2, k+2):
            if m % i == 0:break
        if i == k + 1:
            if n % 10 == 0:print()
            print('%d' % m,end = " ")
            n += 1
    

    输出101到200之间的素数
    每行输出10个,多余换行

    运行:

    101 103 107 109 113 127 131 137 139 149 
    151 157 163 167 173 179 181 191 193 197 
    199
    

    素数(质数)是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

    4. 阅读下面的Python程序,请问输出的结果使什么?

    n = int(input("请输入图形的行数:"))
    for i in range(0, n):
        for j in range(0, 10 - i):print(" ", end=" ")
        for k in range(0, 2 * i + 1):print(" * ", end=" ")
        print("\n")
    

    输出的是一个金字塔

    运行:

    请输入图形的行数:4
                         *  
    
                       *   *   *  
    
                     *   *   *   *   *  
    
                   *   *   *   *   *   *   *  
    

    5. 阅读下面的Python程序,请问输出的结果使什么?程序的功能是什么?

    for i in range(100,1000):
        n1 = i // 100
        n2 = i // 10 % 10
        n3 = i % 10
        if(pow(n1, 3) + pow(n2, 3) + pow(n3, 3) == i):print(i, end=" ")
    

    输出三位数中所有的水仙花数

    运行:

    153 370 371 407 
    

    水仙花数 是指一个 3 位数,它的每个位上的数字的 3次幂之和等于它本身

    6. 阅读下面的Python程序,请问输出的结果使什么?程序的功能是什么?

    for n in range(1,1001):
        total = 0; factors = []
        for i in range(1, n):
            if(n % i == 0):
                factors.append(i)
                total += i
        if(total == n):print("{0} : {1}".format(n, factors))    
    

    输出1到1000的所有完数,并输出每个完数的所有因子

    运行:

    6 : [1, 2, 3]
    28 : [1, 2, 4, 7, 14]
    496 : [1, 2, 4, 8, 16, 31, 62, 124, 248]
    

    完数 所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身

    上机实践:2~14

    2. 编写程序,计算1=2+3+…+100之和

    1. 使用for循环(递增):
    total = 0
    for i in range(101):
        total += i
    print(total) 
    
    1. 使用求和公式:
    >>> (1 + 100) * 100 /2
    5050.0
    
    1. 使用累计迭代器itertools.accumulate
    >>> import itertools
    >>> list(itertools.accumulate(range(1, 101)))[99]
    5050
    

    3. 编写程序,计算10+9+8+…+1之和

    1. 使用for循环(递增):
    total = 0
    for i in range(11):
        total += i
    print(total) 
    
    1. 使用for循环(递减):
    total = 0
    for i in range(10,0,-1):
        total += i
    print(total)   
    
    1. 使用求和公式:
    >>> (1 + 10) * 10 / 2
    55.0
    
    1. 使用累计迭代器itertools.accumulate
    >>> import itertools
    >>> list(itertools.accumulate(range(1,11)))[9]
    55
    

    4. 编写程序,计算1+3+5+7+…+99之和

    1. 使用for循环(递增):
    total = 0
    for i in range(1,100,2):
        total += i
    print(total)     
    
    1. 使用求和公式:
    >>> (1 + 99) * 50 /2
    2500.0
    
    1. 使用累计迭代器itertools.accumulate
    >>> import itertools
    >>> list(itertools.accumulate(range(1,100,2)))[49]
    2500
    

    5. 编写程序,计算2+4+6+8+…+100之和

    1. 使用for循环(递增):
    total = 0
    for i in range(2,101,2):
        total += i
    print(total)     
    
    1. 使用求和公式:
    >>> (2 + 100) * 50 / 2
    2550.0
    
    1. 使用累计迭代器itertools.accumulate
    >>> import itertools
    >>> x = list(itertools.accumulate(range(2,101,2)))
    >>> x[len(x)-1]
    2550
    

    6. 编写程序,使用不同的实现方法输出2000~3000的所有闰年

    代码一:

    for y in range(2000,3001):
        if((y % 4 == 0 and y % 100 != 0) or y % 400 == 0):
            print(y,end = ' ')
    

    代码二(使用calendar模块的isleap()函数来判断):

    from calendar import isleap
    
    for y in range(2000,3001):
        if(isleap(y)):print(y,end = " ")
    

    运行:

    2000 2004 2008 2012 2016 2020 2024 2028 2032 2036 2040 2044 2048 2052 2056 2060 2064 2068 2072 2076 2080 2084 2088 2092 2096 2104 2108 2112 2116 2120 2124 2128 2132 2136 2140 2144 2148 2152 2156 2160 2164 2168 2172 2176 2180 2184 2188 2192 2196 2204 2208 2212 2216 2220 2224 2228 2232 2236 2240 2244 2248 2252 2256 2260 2264 2268 2272 2276 2280 2284 2288 2292 2296 2304 2308 2312 2316 2320 2324 2328 2332 2336 2340 2344 2348 2352 2356 2360 2364 2368 2372 2376 2380 2384 2388 2392 2396 2400 2404 2408 2412 2416 2420 2424 2428 2432 2436 2440 2444 2448 2452 2456 2460 2464 2468 2472 2476 2480 2484 2488 2492 2496 2504 2508 2512 2516 2520 2524 2528 2532 2536 2540 2544 2548 2552 2556 2560 2564 2568 2572 2576 2580 2584 2588 2592 2596 2604 2608 2612 2616 2620 2624 2628 2632 2636 2640 2644 2648 2652 2656 2660 2664 2668 2672 2676 2680 2684 2688 2692 2696 2704 2708 2712 2716 2720 2724 2728 2732 2736 2740 2744 2748 2752 2756 2760 2764 2768 2772 2776 2780 2784 2788 2792 2796 2800 2804 2808 2812 2816 2820 2824 2828 2832 2836 2840 2844 2848 2852 2856 2860 2864 2868 2872 2876 2880 2884 2888 2892 2896 2904 2908 2912 2916 2920 2924 2928 2932 2936 2940 2944 2948 2952 2956 2960 2964 2968 2972 2976 2980 2984 2988 2992 2996 
    

    7. 编写程序,计算Sn=1-3+5-7+9-11…

    代码一:

    n = int(input("项数:"))
    total = 0
    flag = True
    for i in range(1,2*n,2):
        if(flag):
            total += i
            flag = False
        else:
            total -= i
            flag = True
    print(total)
    

    代码二:

    n = int(input("项数:"))
    total = 0
    x = 2
    for i in range(1,2*n,2):
        total += pow(-1,x)*i
        x += 1 
    print(total)
    

    运行:

    项数:10
    -10
    

    8. 编写程序,计算Sn=1+1/2+1/3+…

    n = int(input("项数:"))
    total = 0.0
    for i in range(1,n+1):
        total += 1/i 
    print(total)
    

    运行:

    项数:10
    2.9289682539682538
    

    9. 编写程序,打印九九乘法表。要求输入九九乘法表的各种显示效果(上三角,下三角,矩形块等方式)

    矩形块:

    for i in range(1,10):
        s = ""
        for j in range(1,10):
            s += str.format("%d * %d = %02d  " %(i, j, i*j))
        print(s)
    

    下三角:

    for i in range(1,10):
        s = ""
        for j in range(1,i+1):
            s += str.format("%d * %d = %02d  " %(i, j, i*j))
        print(s)
    

    上三角:

    for i in range(1,10):
        s = ""
        for k in range(1,i):
            s += "                   "
        for j in range(i,10):
            s += str.format("%d * %d = %02d  " %(i, j, i*j))
        print(s)
    

    10. 编写程序,输入三角形的三条边,先判断是否可以构成三角形,如果可以,则进一步求三角形的周长和面积,否则报错“无法构成三角形!”

    from math import sqrt
    
    a = float(input("请输入三角形的边长a:"))
    b = float(input("请输入三角形的边长b:"))
    c = float(input("请输入三角形的边长c:"))
    
    if(a < b): a,b = b,a
    if(a < c): a,c = c,a
    if(b < c): b,c = c,b
    
    if(a < 0 or b < 0 or c < 0 or b+c <= a): print("无法构成三角形!")
    else:
        h = (a+b+c)/2
        area = sqrt(h*(h-a)*(h-b)*(h-c))
        print("周长:{0},面积:{1}".format(a+b+c,area))
    

    运行:

    请输入三角形的边长a:4
    请输入三角形的边长b:3
    请输入三角形的边长c:5
    周长:12.0,面积:6.0
    

    11. 编写程序,输入x,根据如下公式计算分段函数y的值。请分别用单分支语句,双分支语句结构以及条件运算语句等方法实现

    y = (x2-3x)/(x+1) + 2π + sinx (x≥0 )
    y = ln(-5x) + 6√(|x|+e4) - (x+1)3 (x<0)

    单分支语句:

    import math
    
    x = float(input("请输入x:"))
    if(x >= 0):
        y = (x*x - 3*x)/(x+1) + 2*math.pi + math.sin(x)
    if(x < 0):
        y = math.log(-5*x) + 6 * math.sqrt(abs(x) + math.exp(4)) - pow(x+1,3)
    
    print(y)
    
    
    

    双分支语句:

    import math
    
    x = float(input("请输入x:"))
    if(x >= 0):
        y = (x*x - 3*x)/(x+1) + 2*math.pi + math.sin(x)
    else:
        y = math.log(-5*x) + 6 * math.sqrt(abs(x) + math.exp(4)) - pow(x+1,3)
    
    print(y)
    

    条件运算语句:

    import math
    
    x = float(input("请输入x:"))
    y = ((x*x - 3*x)/(x+1) + 2*math.pi + math.sin(x)) if(x >= 0) \
    else (math.log(-5*x) + 6 * math.sqrt(abs(x) + math.exp(4)) - pow(x+1,3)) 
    
    print(y)
    

    运行一:

    请输入x:666
    668.2715406628656
    

    运行二:

    请输入x:-666
    294079794.1744833
    

    12. 编写程序,输入一元二次方程的3个系数a、b、c,求ax2+bx+c=0方程的解

    import math
    
    a = float(input("请输入系数a:"))
    b = float(input("请输入系数b:"))
    c = float(input("请输入系数c:"))
    
    delta = b*b -4*a*c
    
    if(a == 0):
        if(b == 0): print("无解")
        else: print("有一个实根:",-1*c/b)
    elif(delta == 0): print("有两个相等实根:x1 = x2 = ", (-1*b)/(2*a))
    elif(delta > 0): print("有两个不等实根:x1 = {0},x2 = {1}".format\
                           ((-1*b +math.sqrt(delta))/2*a,(-1*b -math.sqrt(delta))/2*a))
    elif(delta < 0): print("有两个共轭复根:x1 = {0},x2 = {1}".format\
                           (complex( (-1*b)/(2*a),math.sqrt(delta*-1)/(2*a)),complex( (-1*b)/(2*a),-1*math.sqrt(delta*-1)/(2*a))))
    

    运行一:

    请输入系数a:0
    请输入系数b:0
    请输入系数c:10
    无解
    

    运行二:

    请输入系数a:0
    请输入系数b:10
    请输入系数c:5
    有一个实根: -0.5
    

    运行三:

    请输入系数a:1
    请输入系数b:8
    请输入系数c:16
    有两个相等实根:x1 = x2 =  -4.0
    

    运行四:

    请输入系数a:1
    请输入系数b:-5
    请输入系数c:6
    有两个不等实根:x1 = 3.0,x2 = 2.0
    

    运行五:

    请输入系数a:5
    请输入系数b:2
    请输入系数c:1
    有两个共轭复根:x1 = (-0.2+0.4j),x2 = (-0.2-0.4j)
    

    13. 编写程序,输入整数n(n≥0),分别利用for循环和while循环求n!

    1. for循环
    n = int(input("请输入n:"))
    
    if(n == 0): total = 1
    if(n > 0):
        total = 1
        for i in range(n,0,-1):
            total *= i
    
    print(total)
    
    
    1. while循环
    n = int(input("请输入n:"))
    
    if(n == 0): total = 1
    if(n > 0):
        total = 1
        while(n >= 1):
            total *= n
            n -= 1
    
    print(total)
    
    1. 补充一个:使用累计迭代器itertools.accumulate
    >>> import itertools, operator
    >>> n = int(input('请输入n:'))
    请输入n:7
    >>> x = list(accumulate(range(1, n+1), operator.mul))
    >>> x[len(x)-1]
    5040
    

    14. 编写程序,产生两个0~100(包含0和100)的随机整数a和b,求这两个整数的最大公约数和最小公倍数

    1. 现有知识点解决方法
    
    import random
    
    a = random.randint(0,100)
    b = random.randint(0,100)
    sum = a*b
    
    print(a) #输出原来的a,b
    print(b)
    
    if(a < b): a,b = b,a
    
    while(a%b != 0):
        a,b = b,a%b
    
    print("最大公约数:{0},最小公倍数:{1}".format(b,sum/b))
    
    
    1. 补充:使用生成器(generate)函数:yield
    >>> def func(a, b):
    	if(a < b): a,b = b,a
    	while(a%b != 0):
    		a,b = b,a%b
    		yield b
    
    		
    >>> import random
    >>> if __name__ == '__main__':
    	a = random.randint(0,100)
    	b = random.randint(0,100)
    	sum = a*b
    	print(a,b)
    	t = list(iter(func(a, b)))
    	gcd = t[len(t)-1]
    	print("gcd = {0}, mcm = {1}".format(gcd, sum/gcd))
    
    	
    29 65
    gcd = 1, mcm = 1885.0
    
    1. 补充:使用math模块中的gcd(x,y)函数
    >>> import random
    >>> import math
    >>> if __name__ == '__main__':
    	a = random.randint(0,100)
    	b = random.randint(0,100)
    	sum = a*b
    	print(a,b)
    	gcd = math.gcd(a,b)
    	print("gcd = {0}, mcm = {1}".format(gcd, sum/gcd))
    
    	
    29 48
    gcd = 1, mcm = 1392.0
    

    案例研究:使用嵌套循环实现图像处理算法

    https://blog.csdn.net/Zhangguohao666/article/details/103935185

    通过图像处理算法案例,深入了解Python数据结构和基本算法流程

    第四章 常用内置数据类型


    几个例题

    一:Python内置数据类型概述

    Python中一切皆为对象,而每个对象属于某个数据类型

    Python的数据类型包括:

    1. 内置的数据类型
    2. 模块中定义的数据类型
    3. 用户自定义的类型

    四种内置的数值类型:int,float,bool,complex

    1. int
      与其他计算机语言有精度限制不同,Python中的整数位数可以为任意长度(只受限于计算机内存)。
      整型对象是不可变对象。
    2. float
      与其他计算机语言中的double和float对应
      Python的浮点类型的精度和系统相关
    3. bool
    4. complex
      当数值字符串中包含虚部j(或J)时即复数字面量

    序列数据类型:str,tuple,bytes,list,bytearray

    序列数据类型表示若干有序数据.

    不可变序列数据类型:

    1. str(字符串)
      表示Unicode字符序列,例如:“zgh666”
      在Python中没有独立的字符数据类型,字符即长度为1的字符串
    2. tuple(元组)
      表示任意数据类型的序列,例如:(“z”,“g”,“h”,6,6,6)
    3. bytes(字节序列)
      表示字节(8位)序列数据

    可变序列数据类型:

    1. list(列表)
      表示可以修改的任意类型数据的序列,比如:[‘z’,‘g’,‘h’,6,6,6]
    2. bytearray(字节数组)
      表示可以修改的字节(8位)数组

    集合数据类型:set,frozenset

    集合数据类型表示若干数据的集合,数据项目没有顺序,且不重复

    1. set(集)
      例如:{1,2,3}
    2. frozenset(不可变集)

    字典数据类型:dict

    字典数据类型用于表示键值对的字典
    例如:{1:"zgh", 2:666}

    NoneType,NotImplementedType,EllipsisType

    1. NoneType数据类型包含唯一值None,主要用于表示空值,如没有返回值的函数的结果
    2. NotImplementedType数据类型包含唯一值NotImplemented,在进行数值运算和比较运算时,如果对象不支持,则可能返回该值
    3. EllipsisType数据类型包含唯一值Ellipsis,表示省略字符串符号...

    其他数据类型

    Python中一切对象都有一个数据类型,模块、类、对象、函数都属于某种数据类型
    Python解释器包含内置类型,
    例如:
    代码对象Code objects
    框架对象Frame objects
    跟踪对象Traceback objects
    切片对象Slice objects
    静态方法对象Static method objects
    类方法对象Class method objects

    二:整型字面量示例

    Python3.7支持使用下划线作为整数或者浮点数的千分位标记,以增强大数值的可阅读性。
    二进制、八进制、十六进制则使用下划线区分4位标记

    1_000_000_000  #输出1000000000
    
    0xff_ff_ff_ff  #输出4294967295
    0x_FF_FF_FF_FF  #输出4294967295
    

    三:字符串字面量示例

    两个紧邻的字符串,如果中间只有空格分隔,则自动拼接位一个字符串

    'zgh' '666'  #输出'zgh666'
    'zgh' + "666"   #输出'zgh666'
    

    四:转义字符示例

    转义字符后跟Unicode编码也可以表示字符

    1. \ooo八进制Unicode码对应的字符
    2. \xhh十六进制Unicode码对应的字符
    '\101'  #输出'A'
    '\x41'  #输出'A'
    

    使用r’‘或者R’'的字符串称为原始字符串,其中包含的任何字符都不进行转义

    s = r'换\t行\t符\n'
    s  		  #输出:'换\\t行\\t符\\n'
    print(s)  #输出:换\\t行\\t符\\n
    

    五:字符串的格式化

    一:

    "student number:{0},score_average:{1}".format(2,100)
    #输出:'student number:2,score_average:100'
    

    二:

    str.format("student number:{0},score_average:{1}",2,100)
    #输出:'student number:2,score_average:100'
    

    三(兼容Python2的格式,不推荐使用):

     "student number:%4d,score_average:%2.1f" %(2,100)
     #输出:'student number:   2,score_average:100.0'
    

    六:字符串示例,格式化输出字符串堆积的三角形

    1. str.center()方法用于字符串两边填充
    2. str.rjust()方法用于字符串右填充
    print("1".center(20))		#一行20个字符,居中对齐
    print(format("121","^20"))	#一行20个字符,居中对齐
    print("1".rjust(20,"*"))	#一行20个字符,右对齐,加*
    print(format("121","*>20"))	#一行20个字符,右对齐,加*
    

    运行:

             1          
            121         
    *******************1
    *****************121
    

    选择题:11

    11. 关于Python字符串,下列说法错误的是

    A. 字符即长度为1的字符串
    B. 字符串以/0标识字符串的结束
    C. 用户既可以用单引号,也可以用双引号创建字符串
    D. 用三引号字符串中可以包含换行回车等特殊字符

    答案:B

    Python中字符串不是用\0来判断字符串结尾,
    每个字符串都存有字符串的长度,通过计数来判断是否到达结尾。

    虽然在c语言中\0就是来判断字符串的结尾;

    填空题:4、7、8、9、10、13、21

    4. Python表达式3 ** 2 ** 3的值为

    答案:6561

    表达式中,相同优先级的运算,从右往左

    7. Python语句print(pow(-3,2),round(18.67,1),round(18.67,-1))的输出结果是

    答案:9 18.7 20.0

    pow()幂运算
    round()四舍六入,五留双

    8. Python语句print(round(123.84,0),round(123.84,-2),floor(15.5))的输出结果是

    答案:124.0 100.0 15

    补充:floor()是math模块中的方法,向下取整

    9. Python语句print(int(‘20’,16),int(‘101’,2))的输出结果是

    答案:32 5

    注意:int(x,y)是指将y进制的数值x转化为10进制数

    10. Python语句print(hex(16),bin(10))的输出结果是

    答案:0x10 0b1010

    hex(x)将十进制数x转化为十六进制,以字符串形式输出
    bin(x)将十进制数x转化为二进制,以字符串形式输出

    13. Python语句print(gcd(12,16),divmod(7,3))的输出结果是

    答案:4 (2,1)

    gcd()是math模块中的函数,求最大公约数
    divmod()是内置函数,返回商和余数

    21. Python语句序列 x=True;y=False;z=False;print(x or y and z) 的运行结果是

    答案:True

    and优先级比or高

    思考题:5

    5. 阅读下面的Python程序,请问输出结果是什么?

    from decimal import *
    
    ctx = getcontext()
    ctx.prec = 2
    print(Decimal('1.78'))#1.78
    print(Decimal('1.78') + 0)#1.8
    ctx.rounding = ROUND_UP
    print(Decimal('1.65') + 0)#1.7
    print(Decimal('1.62') + 0)#1.7
    print(Decimal('-1.45') + 0)#-1.5
    print(Decimal('-1.42') + 0)#-1.5
    ctx.rounding = ROUND_HALF_UP
    print(Decimal('1.65') + 0)#1.7
    print(Decimal('1.62') + 0)#1.6
    print(Decimal('-1.45') + 0)#-1.5
    ctx.rounding = ROUND_HALF_DOWN
    print(Decimal('1.65') + 0)#1.6
    print(Decimal('-1.45') + 0)#-1.4
    

    上机实践:2~14

    2. 编写程序,格式化输出杨辉三角

    杨辉三角即二项式定理的系数表,各元素满足如下条件:第一列及对角线上的元素均为1;其余每个元素等于它上一行同一列元素与前一列元素之和

    我使用了一个更加精妙的规律
    比如第一行为1
    第二行:01 + 10 = 11
    第三行:011 + 110 = 121
    第四行:0121 + 1210 = 1331
    。。。

    def generate(numRows):
        l1 = [1]
        n = 0
        while n < numRows:
            print(str(l1).center(66))
            l1 = [sum(t) for t in zip([0] + l1, l1 + [0])]  #利用zip函数算出每一行 如第二行 zip([0,1],[1,0])=[1,1],以此类推
            n += 1
    a=int(input("请输入行数"))
    generate(a)
    

    运行:

    请输入行数4
                                   [1]                                
                                  [1, 1]                              
                                [1, 2, 1]                             
                               [1, 3, 3, 1]  
    

    3. 输入直角三角形的两个直角边,求三角形的周长和面积,以及两个锐角的度数。结果保留一位小数

    import math
    
    a = float(input("请输入直角三角形的直角边a:"))
    b = float(input("请输入直角三角形的直角边b:"))
    c = math.sqrt(a*a+b*b)
    
    p = a + b + c
    area = 0.5*a*b
    print("三角形的周长:{0:1.1f},面积:{1:1.1f}".format(p,area))
    
    sina = a/c
    sinb = b/c
    
    a_degree = round(math.asin(sina) * 180 / math.pi,0)
    b_degree = round(math.asin(sinb) * 180 / math.pi,0)
    
    print("三角形直角边a的度数:{0},b的度数:{1}".format(a_degree,b_degree))
    

    运行:

    请输入直角三角形的直角边a:3
    请输入直角三角形的直角边b:4
    三角形的周长:12.0,面积:6.0
    三角形直角边a的度数:37.0,b的度数:53.0
    

    4. 编程产生0~100(包含0和100)的三个随机数a、b、c,要求至少使用两种不同的方法,将三个数按从小到大的顺序排序

    方法一:

    import random
    
    a = random.randint(0, 100)
    b = random.randint(0, 100)
    c = random.randint(0, 100)
    
    print(str.format("原始值:{0},{1},{2}", a, b, c))
    
    if(a > b): a,b = b,a
    if(a > c): a,c = c,a
    if(b > c): b,c = c,b
    
    print(str.format("增序:{0},{1},{2}", a, b, c))
    

    方法二(使用内置函数max、min、sum):

    import random
    
    a = random.randint(0, 100)
    b = random.randint(0, 100)
    c = random.randint(0, 100)
    
    print(str.format("原始值:{0},{1},{2}", a, b, c))
    
    maxx = max(a, b, c)
    minx = min(a, b, c)
    median = sum([a, b, c]) - minx - maxx
    
    print(str.format("增序:{0},{1},{2}", minx, median, maxx))
    

    方法三(使用内置函数sorted):

    >>> import random
    >>> a = random.randint(0,100)
    >>> b = random.randint(0,100)
    >>> c = random.randint(0,100)
    >>> print("init value: {0} , {1} , {2}".format(a,b,c))
    init value: 17 , 6 , 59
    >>> sorted([a,b,c])
    [6, 17, 59]
    

    5. 编程计算有固定工资收入的党员每月所缴纳的党费。

    工资基数3000元及以下者,交纳工资基数的0.5%
    工资基数3000~5000元者,交纳工资基数的1%
    工资基数在5000~10000元者,交纳工资基数的1.5%
    工资基数超过10000元者,交纳工资基数的2%

    salary = float(input("请输入有固定工资收入的党员的月工资:"))
    if salary <= 3000: dues = salary*0.005
    elif salary <= 5000: dues = salary*0.01
    elif salary <= 10000: dues = salary*0.15
    else: dues = salary*0.02
    
    print("交纳党费:",dues)
    

    运行:

    请输入有固定工资收入的党员的月工资:10001
    交纳党费: 200.02
    

    6. 编程实现袖珍计算器,要求输入两个操作数和一个操作符(+、-、*、/、%),根据操作符输出运算结果。注意/和%运算符的零异常问题

    a = float(input("请输入操作数(左):"))
    b = float(input("请输入操作数(右):"))
    operator = input("请输入操作符(+、-、*、/、%):")
    
    if(b == 0 and (operator == '/' or operator == '%')):
        print("分母为零,异常!")
    else:
        if operator == '+': result = a+b
        elif operator == '-': result = a-b
        elif operator == '*': result = a*b
        elif operator == '/': result = a/b
        elif operator == '%': result = a%b
        print("{0} {1} {2}= {3}:".format(a,operator,b,result))
    

    运行:

    请输入操作数(左):10
    请输入操作数(右):5
    请输入操作符(+、-、*、/、%):+
    10.0 + 5.0= 15.0:
    

    7. 输入三角形的3条边a、b、c,判断此3边是否可以构成三角形。若能,进一步判断三角形的性质,即为等边、等腰、直角或其他三角形

    a = float(input("请输入三角形的边a:"))
    b = float(input("请输入三角形的边b:"))
    c = float(input("请输入三角形的边c:"))
    
    if(a > b): a,b = b,a
    if(a > c): a,c = c,a
    if(b > c): b,c = c,b
    
    result = "三角形"
    if(not(a>0 and b>0 and c>0 and a+b>c)):
        result = '此三边无法构成三角形'
    else:
        if a == b == c: result = '等边三角形'
        elif(a==b or a==c or b==c): result = '等腰三角形'
        elif(a*a+b*b == c*c): result = '直角三角形'
    
    print(result)
    

    运行:

    请输入三角形的边a:3
    请输入三角形的边b:4
    请输入三角形的边c:5
    直角三角形
    

    8. 编程实现鸡兔同笼问题

    已知在同一个笼子里共有h只鸡和兔,鸡和兔的总脚数为f,其中h和f由用户输入,求鸡和兔各有多少只?要求使用两种方法:一是求解方程;二是利用循环进行枚举测试

    h = int(input("请输入总头数:"))
    f = int(input("请输入总脚数:"))
    
    def fun1(h,f):
        rabbits = f/2-h
        chicken = h-rabbits
        if(chicken < 0 or rabbits < 0): return '无解'
        return chicken,rabbits
    
    def fun2(h,f):
        for i in range(0,h+1):
            if(2*i + 4*(h-i) == f):return i,h-i
        return '无解'
    
    if(h>0 and f>0 and f % 2 == 0):
        if fun1(h,f)=='无解':
            print("无解")
        else:
            print("方法一:鸡:{0},兔:{1}".format(fun1(h,f)[0],fun1(h,f)[1]))
            print("方法二:鸡:{0},兔:{1}".format(fun2(h,f)[0],fun2(h,f)[1]))
    else:
        print('输入的数据无意义')    
    

    运行:

    请输入总头数:100
    请输入总脚数:100
    无解
    

    9. 输入任意实数x,计算ex的近似值,直到最后一项的绝对值小于10-6为止

    ex = 1 + x + x2/2 + x3/3! + x4/4! + … + xn/n!

    x = int(input("请输入任意实数:"))
    
    e = 1
    i = 1
    t = 1
    a = 1
    while(a >= 10e-6):
        t *= i
        a = pow(x,i)/t
        e += a
        i += 1
    
    print(e)
    

    运行:

    请输入任意实数:1
    2.7182815255731922
    

    我发现了在Python中10e-6pow(10,-6)是有差别的,将上述代码中的10e-6改为pow(10,-6),输出结果会有细微的差别

    运行:

    请输入任意实数:1
    2.7182818011463845
    

    10. 输入任意实数a(a>=0),用迭代法求x=√a,要求计算的相对偏差小于10-6

    求平方根的公式:

    Xn+1 = 0.5(Xn + a/Xn)

    import math
    
    a = int(input("请输入任意实数a(>=0):"))
    
    x = a / 2
    y = (x + a/x) / 2
    
    while(abs(y-x) >= pow(10,-6)):
        x = y
        y = (x + a/x) / 2
    
    print(y)
    

    运行:

    请输入任意实数a(>=0):2
    1.414213562373095
    

    11. 即有一个数,用3除余2,用5除余3,用7除余2,请问0~1000中这样的数有哪些?

    我国古代有位大将,名叫韩信。他每次集合部队,只要求部下先后按1-3,1-5,1-7报数,然后再报告一下各队每次报数的余数,他就知道到了多少人。他的这种巧妙算法被人们称作“鬼谷算”,也叫“隔墙算”,或称为“韩信点兵”,外国人还称它为“中国余数定理”。

    for i in range(0,1001):
        if((i % 3 == 2 )and (i % 5 == 3) and (i % 7 == 2)): print(i, end="  ")
    

    运行:

    23  128  233  338  443  548  653  758  863  968
    

    12. 一球从100米的高度自由下落,每次落地后反弹回原高度的一半,再落下。求小球在第10次落地时共经过多少米?第10次反弹多高

    规律:
    第一次下落时的高度:100
    第二次下落时的高度(第一次反弹的高度):50
    第三次下落时的高度(第二次反弹的高度):25

    n = 10
    
    h_down = 100
    h_up = 0
    sum = 0
    for i in range(1,n+1):
        sum += h_down+h_up
        h_down = h_up = h_down/2
    
    print("小球在第十次落地时共经过:{0}米,第十次反弹高度:{1}米".format(sum,h_up))    
    

    运行:

    小球在第十次落地时共经过:299.609375米,第十次反弹高度:0.09765625米
    

    13. 猴子吃桃问题

    猴子第一天摘下若干个桃子,当天吃掉一半多一个;第二天接着吃了剩下的桃子的一半多一个;以后每天都吃了前一天剩下的桃子的一半多一个。到第八天发现只剩一个桃子了。请问猴子第一天共摘了多少个桃子?

    这是一个递推问题

    某天所剩桃子数x
    后一天所剩桃子数y = x - (x/2+1) = x/2-1

    则x = 2(y+1)

    result = 1
    for i in range(8,0,-1):
        print("第{0}天桃子数:{1}".format(i,result))
        result = 2*(result+1)
    

    运行:

    第8天桃子数:1
    第7天桃子数:4
    第6天桃子数:10
    第5天桃子数:22
    第4天桃子数:46
    第3天桃子数:94
    第2天桃子数:190
    第1天桃子数:382
    

    14. 计算Sn = 1+11+111+…+111…111(最后一项是n个1)。n是一个随机产生的1~10(包括1和10)中的正整数

    import random
    
    n = random.randint(1,10)
    
    x = 1
    s = 0
    for i in range(1,n+1):
        s += x
        x = 10*x+1
    
    print("n = {0},sn = {1}".format(n,s))
    

    运行:

    n = 6,sn = 123456
    

    random.randint(a, b)

    • 生成指定范围内的整数
    • 范围:[a, b]

    案例研究:科学计算和数据分析

    https://blog.csdn.net/Zhangguohao666/article/details/103941448

    通过Python科学计算和数据分析库的安装和基本使用,了解使用Python进行科学计算的基本方法

    第五章 序列数据类型


    几个例题

    一:Python中内置的序列数据类型

    • 元组也称为定值表,用于存储固定不变的表
    • 列表也称为表,用于存储其值可变的表
    • 字符串是包括若干字符的序列数据,支持序列数据的基本操作
    • 字节序列数据是包括若干字节的序列。Python抓取网页时返回的页面通常为utf-8编码的字节序列。

    字节序列和字符串可以直接相互转换(字节编码和解码):

    >>> s1 = b'abc'
    >>> s1
    b'abc'
    >>> s1.decode("utf-8")
    abc
    
    >>> s2 = "中国"
    >>> s2.encode("utf-8")
    b'\xe4\xb8\xad\xe5\x9b\xbd'
    

    二:序列的切片操作示例

    >>> s = 'zgh666'
    >>> s[0]
    'z'
    >>> s[2]
    'h'
    >>> s[:3]
    'zgh'
    >>> s[1:3]
    'gh'
    >>> s[3:6]
    '666'
    >>> s[3:55]
    '666'
    >>> s[::-1]
    '666hgz'
    >>> s[3:2]
    ''
    >>> s[:]
    'zgh666'
    >>> s[::2]
    'zh6'
    

    三:序列的连接和重复操作

    • 通过连接操作符+可以连接两个序列,形成一个新的序列对象
    • 通过重复操作符*可以重复一个序列n次
    • 连接操作符和重复操作符也支持复合赋值运算,即:+=*=
    >>> x = 'zgh'
    >>> y = '666'
    >>> x + y
    'zgh666'
    >>> x *2
    'zghzgh'
    >>> x += y
    >>> x
    'zgh666'
    >>> y *= 3
    >>> y
    '666666666'
    

    四:序列的成员关系操作

    • in
    • not in
    • s.count(x)
      x在s中出现的次数
    • s.index(x)
      x在s中第一次出现的下标
    >>> s = "zgh666"
    >>> 'z' in s
    True
    >>> 'g' not in s
    False
    >>> s.count('6')
    3
    >>> s.index('6')
    3
    

    五:序列的排序操作

    sorted(iterable,key=None,reverse=False)

    >>> sorted(s)
    [1, 3, 5, 9]
    >>> sorted(s,reverse=True)
    [9, 5, 3, 1]
    
    >>> s = 'zGhZgH'
    >>> sorted(s)
    ['G', 'H', 'Z', 'g', 'h', 'z']
    >>> sorted(s,key=str.lower)
    ['G', 'g', 'h', 'H', 'z', 'Z']
    >>> sorted(s,key=str.lower,reverse=True)
    ['z', 'Z', 'h', 'H', 'G', 'g']
    

    六:序列的拆分

    1. 变量个数与序列长度相等
      若变量个数与序列的元素个数不一致,将导致ValueError
    >>> data = (118,'zgh',(100,100,100))
    >>> sid,name,(chinese,english,math) = data
    >>> sid
    118
    >>> name
    'zgh'
    >>> chinese
    100
    >>> english
    100
    >>> math
    100
    
    1. 变量个数与序列长度不等
      如果序列长度未知,可以使用*元组变量,将多个值作为元组赋值给元组变量。在一个赋值语句中,*元组变量只允许出现一次,否则将导致SyntaxError
    >>> first,second,third,*middles,last = range(10)
    >>> first
    0
    >>> second
    1
    >>> third
    2
    >>> middles
    [3, 4, 5, 6, 7, 8]
    >>> last
    9
    
    >>> first,*middles,last = sorted([58,60,60,100,70,70])
    >>> sum(middles)/len(middles)
    65.0
    
    1. 使用临时变量_
      如果只需要部分数据,序列的其它位置可以使用临时变量_
    >>> record = ['zgh','858990471@qq.com','17354364147','15272502101']
    >>> name,_,*phone = record
    >>> name
    'zgh'
    >>> phone
    ['17354364147', '15272502101']
    

    七:使用元组字面量,tuple创建元组实例对象的实例

    >>> t1 = 1,2,3
    >>> t1
    (1, 2, 3)
    
    >>> t2 = (4,5,6)
    >>> t2
    (4, 5, 6)
    
    >>> t3 = (9,)
    >>> t3
    (9,)
    

    如果元组中只有一个项目,后面的逗号不能省略。

    Python解释器把(1)解释为整数1,将(1,)解释为元组

    >>> t1 = tuple()
    >>> t1
    ()
    
    >>> t2 = tuple("zgh666")
    >>> t2
    ('z', 'g', 'h', '6', '6', '6')
    
    >>> t3 = tuple(['z','g','h'])
    >>> t3
    ('z', 'g', 'h')
    

    八:使用列表字面量,list创建列表实例对象的实例

    >>> l1 = []
    >>> l1
    []
    
    >>> l2 = ['zgh666']
    >>> l2
    ['zgh666']
    
    >>> l3 = [(1,2,3)]
    >>> l3
    [(1, 2, 3)]
    
    >>> l1 = list()
    >>> l1
    []
    
    >>> l2 = list(b'zgh666')
    >>> l2
    [122, 103, 104, 54, 54, 54]
    
    >>> l3 = list(b'aAbBcC')
    >>> l3
    [97, 65, 98, 66, 99, 67]
    

    补充:列表是可变对象,故用户可以改变列表对象中元素的值,也可以通过del删除某元素

    九:列表解析表达式示例

    使用列表解析表达式可以简单,高效地处理一个可迭代对象,并生成结果列表

    >>> [(i,i**2) for i in range(10)]
    [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25), (6, 36), (7, 49), (8, 64), (9, 81)]
    
    >>> [i for i in range(10) if i%2==0]
    [0, 2, 4, 6, 8]
    
    >>> [(x,y,x*y) for x in range(1,4) for y in range(1,4) if x>=y]
    [(1, 1, 1), (2, 1, 2), (2, 2, 4), (3, 1, 3), (3, 2, 6), (3, 3, 9)]
    

    选择题:4、5、7、11、12

    4. Python语句序列“a = (1,2,3,None,(),[]);print(len(a))”的运行结果是

    >>> a = (1,2,3,None,(),[])
    >>> len(a)
    6
    

    5. Python语句序列“nums = set([1,2,2,3,3,3,4]);print(len(nums))”的运行结果是

    >>> nums = set([1,2,2,3,3,3,4])
    >>> nums
    {1, 2, 3, 4}
    >>> len(nums)
    4
    

    7. Python语句序列“s1=[4,5,6];s2=s1;s1[1]=0;print(s2)”的运行结果是

    Python中变量(如s1,s2)存储在栈中,存放的是地址
    [4,5,6]存储在堆中

    s1 = [4,5,6]即s1存储指向堆中[4,5,6]的地址
    s2 = s1地址赋值,即s2和s1都指向同一个地址
    所以对列表进行修改,两者的显示都会发生变化

    >>> s1 = [4,5,6]
    >>> s2 = s1
    >>> s1[1] = 0
    >>> s1
    [4, 0, 6]
    >>> s2
    [4, 0, 6]
    

    11. Python语句序列“s={‘a’,1,‘b’,2};print(s[‘b’])”的运行结果是

    A. 语法错B. ‘b’C. 1D. 2

    答案:A

    通过值访问集合是没有意义的,语法也不支持

    >>> s ={'a',1,'b',2}
    >>> print(s['b'])
    Traceback (most recent call last):
      File "<pyshell#29>", line 1, in <module>
        print(s['b'])
    TypeError: 'set' object is not subscriptable
    

    补充:集合set是无序不重复的,是无法通过下标访问的

    12. Python语句print(r"\nGood")的运行结果是

    A. 新行和字符串GoodB. r"\nGood"C. \nGoodD. 字符r、新行和字符串Good

    答案:C

    >>> print(r"\nGood")
    \nGood
    

    r""声明原始字符串

    填空题:1、5、6、12、13、14

    1. Python语句序列“fruits = [‘apple’,‘banana’,‘bear’];print(fruits[-1][-1])”的运行结果是

    注意:fruit[-1]是字符串’bear’
    所以:fruit[-1][-1]'bear[-1]'

    >>> fruits = ['apple','banana','pear']
    >>> fruits[-1]
    'pear'
    >>> fruits[-1][-1]
    'r'
    

    5. Python语句 print(’%d%%%d’%(3/2,3%2)) 的运行结果是

    >>> print('%d%%%d'%(3/2,3%2))
    1%1
    

    6. Python语句序列“s = [1,2,3,4];s.append([5,6]);print(len(s))”的运行结果是

    答案:5

    注意append()和extend()函数的区别
    s.append(x)将对象x追加到s尾部
    s.extend(x)将序列x追加到s尾部

    append

    >>> s = [1,2,3,4]
    >>> s.append([5,6])
    >>> s
    [1, 2, 3, 4, [5, 6]]
    >>> len(s)
    5
    

    extend

    >>> s = [1,2,3,4]
    >>> s.extend([5,6])
    >>> s
    [1, 2, 3, 4, 5, 6]
    >>> len(s)
    6
    

    12

    >>> s =('a','b','c','d','e')
    >>> s[2]
    'c'
    >>> s[2:3]
    ('c',)
    >>> s[2:4]
    ('c', 'd')
    >>> s[1::2]
    ('b', 'd')
    >>> s[-2]
    'd'
    >>> s[::-1]
    ('e', 'd', 'c', 'b', 'a')
    >>> s[-2:-1]
    ('d',)
    >>> s[-99:-5]
    ()
    >>> s[-99:-3]
    ('a', 'b')
    >>> s[::]
    ('a', 'b', 'c', 'd', 'e')
    >>> s[1:-1]
    ('b', 'c', 'd')
    

    13

    >>> s = [1,2,3,4,5,6]
    >>> s[:1] = []
    >>> s
    [2, 3, 4, 5, 6]
    
    >>> s[:2] = 'a'
    >>> s
    ['a', 4, 5, 6]
    
    >>> s[2:] = 'b'
    >>> s
    ['a', 4, 'b']
    
    >>> s[2:3] = ['x','y']
    >>> s
    ['a', 4, 'x', 'y']
    
    >>> del s[:1]
    >>> s
    [4, 'x', 'y']
    

    14

    >>> s = ['a','b']
    >>> s.append([1,2])
    >>> s
    ['a', 'b', [1, 2]]
    >>> s.extend('34')
    >>> s
    ['a', 'b', [1, 2], '3', '4']
    >>> s.extend([5,6])
    >>> s
    ['a', 'b', [1, 2], '3', '4', 5, 6]
    >>> s.insert(1,7)
    >>> s
    ['a', 7, 'b', [1, 2], '3', '4', 5, 6]
    >>> s.insert(10,8)
    >>> s
    ['a', 7, 'b', [1, 2], '3', '4', 5, 6, 8]
    >>> s
    ['a', 7, 'b', [1, 2], '3', '4', 5, 6]
    >>> s.remove('b')
    >>> s
    ['a', 7, [1, 2], '3', '4', 5, 6]
    >>> s[3:] =[]
    >>> s
    ['a', 7, [1, 2]]
    >>> s.reverse()
    >>> s
    [[1, 2], 7, 'a']
    >>> 
    

    思考题:2、3、5

    2. 阅读下面的Python语句,请问输出结果是什么?

    n = int(input('请输入图形的行数:'))
    
    for i in range(n,0,-1):
        print(" ".rjust(20-i),end=' ')
        for j in range(2*i-1):print(" * ",end=' ')
        print('\n')
    
    for i in range(1,n):
        print(" ".rjust(19-i),end=' ')
        for j in range(2*i+1):print(" * ",end=' ')
        print('\n')          
    

    运行一:

    请输入图形的行数:1
                         *  
    

    运行二:

    请输入图形的行数:2
                        *   *   *  
    
                         *  
    
                        *   *   *  
    

    运行三:

    请输入图形的行数:3
                       *   *   *   *   *  
    
                        *   *   *  
    
                         *  
    
                        *   *   *  
    
                       *   *   *   *   *  
    

    3. 阅读下面的Python语句,请问输出结果是什么?

    n = int(input('请输入上(或下)三角行数:'))
    
    for i in range(0,n):
        print(" ".rjust(19-i),end=' ')
        for j in range(2*i+1):print(" * ",end=' ')
        print('\n')
    
    for i in range(n-1,0,-1):
        print(" ".rjust(20-i),end=' ')
        for j in range(2*i-1):print(" * ",end=' ')
        print('\n')          
    

    运行:

    请输入上(或下)三角行数:4
                         *  
    
                        *   *   *  
    
                       *   *   *   *   *  
    
                      *   *   *   *   *   *   *  
    
                       *   *   *   *   *  
    
                        *   *   *  
    
                         *  
    

    5. 阅读下面的Python语句,请问输出结果是什么?

    先看这三句:

    >>> names1 = ['Amy','Bob','Charlie','Daling']
    >>> names2 = names1
    >>> names3 = names1[:]
    

    毫无疑问,此时names1,names2,names3的值都是[‘Amy’,‘Bob’,‘Charlie’,‘Daling’]
    但是

    >>> id(names1)
    2338529391368
    >>> id(names2)
    2338529391368
    >>> id(names3)
    2338529391560
    

    names1和names2指向同一个地址
    而names3指向另一个地址

    然后:

    >>> names2[0] = 'Alice'
    >>> names3[1] = 'Ben'
    >>> names1
    ['Alice', 'Bob', 'Charlie', 'Daling']
    >>> names2
    ['Alice', 'Bob', 'Charlie', 'Daling']
    >>> names3
    ['Amy', 'Ben', 'Charlie', 'Daling']
    

    最后:

    >>> sum = 0
    >>> for ls in(names1,names2,names3):
    	if ls[0] == 'Alice': sum+=1
    	if ls[1] == 'Ben':sum+=2
    
    	
    >>> print(sum)
    4
    

    上机实践:2~6

    2. 统计所输入字符串中单词的个数,单词之间用空格分隔

    s = input("请输入字符串:")
    
    num = 0
    for i in s:
        if((i >= 'a' and i <= 'z') or (i >= 'A' and i <= 'Z')):
            num += 1
    
    print("其中的单词总数:",num) 
    

    运行:

    请输入字符串:zgh666 ZGH6
    其中的单词总数: 6
    

    3. 编写程序,删除一个list里面重复元素

    方法一:利用set集合不重复的性质(但结果不能保证原来的顺序)

    l = [1,2,2,3,3,3,4,5,6,6,6]
    s = set(l)
    l = list(s)
    print(l)
    

    运行:

    [1, 2, 3, 4, 5, 6]
    

    方法二:既可以去除重复项,又可以保证原来的顺序

    def unique(items):
        items_existed = set()
        for item in items:
            if item not in items_existed:
                yield item
                items_existed.add(item)
    
    if __name__ == '__main__':
        a = [1, 8, 5, 1, 9, 2, 1, 10]
        a1 = unique(a)
        print(list(a1))
    
    

    运行结果:

    [1, 8, 5, 9, 2, 10]
    

    对代码的分析:

    • 可以看出,unique()函数返回的并不是items_existed,而是利用了yield

    在函数定义中,如果使用yield语句代替return返回一个值,则定义了一个生成器函数(generator)
    生成器函数是一个迭代器,是可迭代对象,支持迭代

    • a1 = unique(a) 这个函数返回的实际上是一个可迭代对象
      print(a1)得到的会是:<generator object unique at 0x0000016E23AF4F48>
    • 所以,要得到去掉重复后的列表的样子,需要将可迭代对象a1放在list()中
      运行:

    4. 编写程序,求列表[9,7,8,3,2,1,55,6]中的元素个数、最大值、最小值,以及元素之和、平均值。请思考有几种实现方法?

    内置函数:

    s = [9,7,8,3,2,1,55,6]
    
    print("元素个数:{0},最大值:{1},最小值:{2},和:{3},平均值:{4}".\
          format(len(s),max(s),min(s),sum(s),sum(s)/len(s)))
    

    直接访问元素列表(for i in s…):

    s = [9,7,8,3,2,1,55,6]
    
    sum = 0
    max = s[0]
    min = s[0]
    length = 0
    for i in s:
        sum += i
        length += 1
        if(i > max): max = i
        if(i < min): min = i
    
    print("元素个数:{0},最大值:{1},最小值:{2},和:{3},平均值:{4}".\
          format(length,max,min,sum,sum/length))
    
    

    间接访问列表元素(for i in range(0,len(s))…):

    s = [9,7,8,3,2,1,55,6]
    
    sum = 0
    max = s[0]
    min = s[0]
    length = len(s)
    for i in range(0,length):
        sum += s[i]
        if(s[i] > max): max = s[i]
        if(s[i] < min): min = s[i]
    
    print("元素个数:{0},最大值:{1},最小值:{2},和:{3},平均值:{4}".\
          format(length,max,min,sum,sum/length))
    
    

    正序访问(i=0;while i<len(s)…):

    s = [9,7,8,3,2,1,55,6]
    
    sum = 0
    max = s[0]
    min = s[0]
    length = len(s)
    
    i = 0
    while(i < length):
        sum += s[i]
        if(s[i] > max): max = s[i]
        if(s[i] < min): min = s[i]
        i += 1
    
    print("元素个数:{0},最大值:{1},最小值:{2},和:{3},平均值:{4}".\
          format(length,max,min,sum,sum/length))
    
    

    反序访问(i=len(s)-1;while i>=0…):

    s = [9,7,8,3,2,1,55,6]
    
    sum = 0
    max = s[0]
    min = s[0]
    length = len(s)
    
    i = length-1
    while(i >= 0):
        sum += s[i]
        if(s[i] > max): max = s[i]
        if(s[i] < min): min = s[i]
        i -= 1
    
    print("元素个数:{0},最大值:{1},最小值:{2},和:{3},平均值:{4}".\
          format(length,max,min,sum,sum/length))
    
    

    while True:…break

    s = [9,7,8,3,2,1,55,6]
    
    sum = 0
    max = s[0]
    min = s[0]
    length = len(s)
    
    i = 0
    while(True):
        if(i > length-1): break
        sum += s[i]
        if(s[i] > max): max = s[i]
        if(s[i] < min): min = s[i]
        i += 1
    
    print("元素个数:{0},最大值:{1},最小值:{2},和:{3},平均值:{4}".\
          format(length,max,min,sum,sum/length))
    

    运行:

    元素个数:8,最大值:55,最小值:1,和:91,平均值:11.375
    

    5. 编写程序,将列表[9,7,8,3,2,1,5,6]中的偶数变成它的平方,奇数保持不变

    l = [9,7,8,3,2,1,5,6]
    
    for i,value in enumerate(l):
        if(value % 2 == 0):l[i] = value**2
    
    print(l)
    

    运行:

    [9, 7, 64, 3, 4, 1, 5, 36]
    

    6. 编写程序,输入字符串,将其每个字符的ASCII码形成列表并输出

    s = input("请输入一个字符串:")
    l = list()
    for i in s:
        l.append(ord(i))
    
    print(l)
    

    运行:

    请输入一个字符串:zgh666
    [122, 103, 104, 54, 54, 54]
    

    案例研究:猜单词游戏

    https://blog.csdn.net/Zhangguohao666/article/details/103948234

    通过猜单词游戏的设计和实现,帮助读者了解使用Python系列数据类型和控制流程

    第六章 输入和输出


    几个例题

    一:运行时提示输入密码

    输入密码时,一般需要不明显,则可以使用模块getpass,以保证用户输入的密码在控制台中不回显

    import getpass
    
    username = input("user:")
    password = getpass.getpass("password:")
    if(username == 'zgh' and password == '666'):
        print('logined!')
    else:
        print('failed!')
    
    input()#为了看到输出结果。因为执行完毕后,控制台会立马关闭
    

    注意:上面这个代码,如果使用IDLE执行,会因为安全问题而执行失败

    但是,在控制台中执行就没问题,看输出结果(可以看到,输入的密码不会显示出来):

    user:zgh
    password:
    logined!
    

    二:重定向标准输出到一个文件的示例

    这种重定向由控制台完成,而与Python本身无关。

    格式:
    程序 > 输出文件

    其目的是将显示屏从标准输出中分离,并将输出文件与标准输出关联,即程序的执行结果将写入输出文件,而不是发送到显示屏中显示

    首先准备一个test.py文件(代码如下)

    import sys,random
    
    n = int(sys.argv[1])
    for i in range(n):
        print(random.randrange(0,100))
    

    然后在PowerShell中:python test.py 100 > scores.txt
    记住,切记,一定要注意:千万能省略python,这样写./test.py 100 > scores.txt会出现问题,生成的scores文件中会没有任何内容!!!(原因未知)

    然后在当前目录下,100个[0,100)范围内的的整数生成在scores.txt文件中了

    三:重定向文件到标准输入

    格式:
    程序 < 输入文件

    其目的是将控制台键盘从标准输入中分离,并将输入文件与标准输入关联,即程序从输入文件中读取输入数据,而不是从键盘中读取输入数据

    准备一个average.py文件(代码如下)

    import sys
    
    total =0.0
    count = 0
    for line in sys.stdin:
        count += 1
        total += float(line)
    
    avg = total/count
    print("average:",avg)
    

    然后问题总是不期而至,
    在PowerShell中:python average.py < scores.txt,会报错,PowerShell会提示你:“<”运算符是为将来使用而保留的
    很无奈,我只能使用cmd了,然后得出结果

    四:管道

    格式:
    程序1 | 程序2 | 程序3 | … | 程序4

    其目的是将程序1的标准输出连接到程序2的标准输入,
    将程序2的标准输出连接到程序3的标准输入,以此类推

    例如:
    打开cmd,输入python test.py 100 | average.py,其执行结果等同于上面两个例子中的命令

    使用管道更加简洁,且不用创建中间文件,从而消除了输入流和输出流可以处理的数据大小的限制,执行效率更高

    五:过滤器

    1. 使用操作系统实用程序more逐屏显示数据

    2. 使用操作系统实用程序sort排序输出数据

    more和sort都可以在一个语句中使用

    填空题:1、2

    print(value, ..., sep = ' ', end = '\n', file = sys.stdout, flush = False)

    1. sep(分隔符,默认为空格)
    2. end(换行符,即输入的末尾是个啥)
    3. file(写入到指定文件流,默认为控制台sys.stdout)
    4. flush(指定是否强制写入到流)

    1

    >>> print(1,2,3,4,5,sep='-',end='!')
    1-2-3-4-5!
    

    2

    >>> for i in range(10):
    	print(i,end=' ')
    
    	
    0 1 2 3 4 5 6 7 8 9 
    

    例题及上机实践:2~5

    2. 尝试修改例6.2编写的命令行参数解析的程序,解析命令行参数所输入边长的值,计算并输出正方形的周长和面积

    argparse模块用于解析命名的命令行参数,生成帮助信息的Python标准模块

    例6.2:解析命令行参数所输入的长和宽的值,计算并输出长方形的面积

    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('--length', default = 10, type = int, help = '长度')
    parser.add_argument('--width', default = 5, type = int, help = '宽度')
    
    args = parser.parse_args()
    area = args.length * args.width
    print('面积 = ', area)
    
    input()#加这一句是为了可以看到输出结果
    

    输出:面积 = 50

    如果在执行这个模块时,加入两个命令行参数

    输出:面积 = 36

    基本上看了上面这个例子后,就可以理解argparse的用法了

    本题代码:

    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('--length', default = 10, type = int, help = '长度')
    
    args = parser.parse_args()
    area = args.length ** 2
    perimeter = 4 * args.length
    print('面积 = {0},周长 = {1}'.format(area,perimeter))
    
    input()#加这一句是为了可以看到输出结果
    
    

    在PowerShell中输入.\test.py
    不给命令行参数,输出是以默认值来计算的
    输出:面积 = 100,周长 = 40

    给命令行参数:.\test.py --length 1
    输出:面积 = 1,周长 = 4

    3. 尝试修改例6.8编写读取并输出文本文件的程序,由命令行第一个参数确认所需输出的文本文件名

    f = open(file, mode = 'r' , buffering = -1, encoding = None)

    1. file是要打开或创建的文件名,如果文件不在当前路径,需指出具体路径
    2. mode是打开文件的模式,模式有:
      ‘r’(只读)
      ‘w’(写入,写入前删除就内容)
      ‘x’(创建新文件,如果文件存在,则导致FileExistsError)
      ‘a’(追加)
      ‘b’(二进制文件)
      ‘t’(文本文件,默认值)
      ‘+’(更新,读写)
    3. buffering表示是否使用缓存(缓存为-1,表示使用系统默认的缓冲区大小)
    4. encoding是文件的编码

    例6.8:读取并输出文本文件

    import sys
    
    filename = sys.argv[0]#就读取本文件,骚的呀皮
    f = open(filename, 'r', encoding = 'utf-8')
    
    line_no = 0
    while True:
        line_no += 1
        line = f.readline()
        if line:
            print(line_no, ":", line)
        else:
            break
    f.close()       
    

    输出(代码输出的就是本python文件):

    1 : import sys
    
    2 : 
    
    3 : filename = sys.argv[0]#就读取本文件,骚的呀皮
    
    4 : f = open(filename, 'r', encoding = 'utf-8')
    
    5 : 
    
    6 : line_no = 0
    
    7 : while True:
    
    8 :     line_no += 1
    
    9 :     line = f.readline()
    
    10 :     if line:
    
    11 :         print(line_no, ":", line)
    
    12 :     else:
    
    13 :         break
    
    14 : f.close()
    
    15 :         
    
    

    本题代码:

    对例题代码进行些许修改就可以了,首先将上例中的第二个语句改为:filename = sys.argv[0],再考虑下面怎么进行

    准备一个用来测试的文件test.txt:

    对于这个文件要注意一点(你们很可能回出现这个问题!!!),win10默认创建的文本文件的字符编码是ANSI

    代码怎么写,有两种:

    1. 将test.txt文本文件的编码修改为utf-8,代码如上所说
      记事本方式打开test.txt文件,点击文件,点击另存为,看到下方的编码(修改为utf-8)
    2. test.txt就用默认的ANSI编码方式,再将上例代码的第三个语句修改为f = open(filename, 'r', encoding = 'ANSI')

    在PowerShell中输入:./test.py test.txt
    输出:

    1 : 大家好
    
    2 : 我是Zhangguohao666
    
    3 : 如果本文章对大家有帮助,请点赞支持一下
    
    4 : 还有:
    
    5 : 如果发现了什么问题,请在评论区指出,我会积极改进
    

    4. 尝试修改例6.9编写利用with语句读取并输出文本文件的程序,由命令行第一个参数确认所需输出的文本文件名

    为了简化操作,Python语言中与资源相关的对象可以实现上下文管理协议,可以使用with语句,确保释放资源。
    with open(file,mode) as f:

    例6.9:利用with语句读取并输出文本文件

    import sys
    
    filename = sys.argv[0]
    
    line_no = 0
    with open(filename, 'r', encoding = 'utf-8') as f:
        for line in f:
            line_no += 1
            print(line_no, ":", line)
    f.close()
    

    基本上,看这个例子,就可以上手with语句了

    本题代码:

    还是上一题准备的文本文件,
    代码一(文本文件的编码为默认的ANSI):

    import sys
    
    filename = sys.argv[1]
    
    line_no = 0
    with open(filename, 'r', encoding = 'ANSI') as f:
        for line in f:
            line_no += 1
            print(line_no, ":", line)
    f.close()
          
    

    代码二(将文本文件的编码修改为utf-8):

    import sys
    
    filename = sys.argv[1]
    
    line_no = 0
    with open(filename, 'r', encoding = 'utf-8') as f:
        for line in f:
            line_no += 1
            print(line_no, ":", line)
    f.close()
          
    
    

    本题的输出,我再不要脸的放一次吧:

    1 : 大家好
    
    2 : 我是Zhangguohao666
    
    3 : 如果本文章对大家有帮助,请点赞支持一下
    
    4 : 还有:
    
    5 : 如果发现了什么问题,请在评论区指出,我会积极改进
    

    5. 尝试修改例6.12编写标准输出流重定向的程序,从命令行第一个参数中获取n的值,然后将0-n,0-n的2倍值,2的0-n次幂的列表打印输出到out.log文件中

    例6.12:从命令行第一个参数中获取n的值,然后将0-n,2的0-n次幂的列表打印输出到out.log文件中

    1. 标准输入流文件对象:sys.stdin,
      默认值为sys.__stdin__
    2. 标准输出流文件对象:sys.stdout,
      默认值为sys.__stdout__
    3. 错误输出流文件对象(标准错误流文件对象):sys.stderr
      默认值为sys.__stderr__

    书中给的代码是这样的:

    import sys
    
    n = int(sys.argv[1])
    power = 1
    i = 0
    
    f = open('out.log', 'w')
    sys.stdout = f
    
    while i <= n:
        print(str(i), ' ', str(power))
        power = 2*power
        i += 1
    sys.stdout = sys.__stdout__
    

    如果使用的编辑器是PyCharm(现在大多数编辑器会帮你对代码进行优化和处理一些隐患),运行书中的这个代码没有问题。

    但是:
    若使用的编辑器是python自带的IDLE,运行这个代码有问题!

    第一:out.log文件会生成,但是没有东西
    (发现文件关闭不了(就是×不掉),
    确定是文件没关闭(f.close())的原因)

    第二:控制台没有输出’done’语句(估计是IDLE编辑器处理不了__stdout__这个值)

    经过研究后,发现(基于IDLE编辑器):
    如果在上面的代码中加入f.close()后,该输入的东西都成功输入进out.log文件了,
    但是,
    还有一个问题
    控制台依旧没有输出’done’语句
    经过一步步的断点调试(就是手动写print)
    发现sys.stdout = sys.__stdout__不会执行

    然后进行改动后,就可以了,代码如下:
    (既然__stdout__不好使,就使用中间变量)

    import sys
    
    n = int(sys.argv[1])
    power = 1
    i = 0
    
    output = sys.stdout
    f = open('out.log', 'w')
    sys.stdout = f
    
    while i <= n:
        print(str(i), ' ', str(power))
        power = 2*power
        i += 1
    
    f.close()
    sys.stdout = output
    print('done!')#这一句是用来检测上面的代码是否成功执行
    
    

    问题虽然解决,但是原因没有彻底弄清楚,求助。。。。。。

    本题代码:

    import sys
    
    n = int(sys.argv[1])
    power = 1
    i = 0
    
    output = sys.stdout
    f = open('out.log', 'w')
    sys.stdout = f
    
    while i <= n:
        print(str(i), ' ',  str(2*i),  ' ', str(power))
        power = 2*power
        i += 1
    
    f.close()
    sys.stdout = output
    print('done!')#这一句是用来检测上面的代码是否成功执行
    
    

    比如时输入的命令行参数是6
    输出:

    案例研究:21点扑克牌游戏

    https://blog.csdn.net/Zhangguohao666/article/details/103948545

    通过21点扑克牌游戏的设计和实现,了解使用Python数据类型、控制流程和输入输出

    第七章 错误和异常处理


    Python语言采用结构化的异常处理机制捕获和处理异常

    而我感觉,Python在这方面的知识点其实和Java的差不多

    几个例题

    一:程序的错误和异常处理

    1. 语法错误

    指源代码中的拼写错误,这些错误导致Python编译器无法把Python源代码转换为字节码,故也称之为编译错误

    1. 运行时错误

    在解释执行过程中产生的错误

    例如:

    • 程序中没有导入相关的模块,NameError
    • 程序中包括零除运算,ZeroDivisionError
    • 程序中试图打开不存在的文件,FileNotFoundError
    1. 逻辑错误

    程序可以执行(程序运行本身不报错),但执行结果不正确。
    对于逻辑错误,Python解释器无能为力,需要用户根据结果来调试判断

    大部分由程序错误而产生的错误和异常一般由Python虚拟机自动抛出。另外,在程序中如果判断某种错误情况,可以创建相应的异常类的对象,并通过raise语句抛出

    >>> a = -1
    >>> if(a < 0): raise ValueError("数值不能为负数")
    
    Traceback (most recent call last):
      File "<pyshell#9>", line 1, in <module>
        if(a < 0): raise ValueError("数值不能为负数")
    ValueError: 数值不能为负数
    >>> 
    

    在程序中的某个方法抛出异常后,Python虚拟机通过调用堆栈查找相应的异常捕获程序。如果找到匹配的异常捕获程序(即调用堆栈中的某函数使用try…except语句捕获处理),则执行相应的处理程序(try…except语句中匹配的except语句块)

    如果堆栈中没有匹配的异常捕获程序,则Python虚拟机捕获处理异常,在控制台打印出异常的错误信息和调用堆栈,并中止程序的执行

    二:try …except…else…finally

    try:
    	可能产生异常的语句
    except Exception1:
    	发生Exception1时执行的语句
    except (Exception2,Exception3):
    	发生Exception2或Exception3时执行的语句
    except Exception4 as e:
    	发生Exception4时执行的语句,Exception4的实例是e
    except:
    	捕获其他所有异常
    else:
    	无异常时执行的语句
    finally:
    	不管异常发生与否都保证执行的语句			
    

    except语句可以写多个,但是要注意一点:系统是自上而下匹配发生的异常,所以用户需要将带有最具体的(即派生类程度最高的)异常类的except写在前面

    三:创建自定义异常,处理应用程序中出现的负数参数的异常

    自定义异常类一般继承于Exception或其子类。自定义异常类的名称一般以Error或Exception为后缀

    >>> class NumberError(Exception):
        def __init__(self,data):
            Exception.__init__
            (self,data)
            self.data = data
        def __str__(self):
            return self.data + ':非法数值(<0)'
    
    >>> 
    >>> def total(data):
        total = 0
        for i in data:
            if i < 0: raise NumberError(str(i))
            total += 1
        return total
    
    >>> 
    >>> data1 = (44, 78, 90, 80, 55)
    >>> print("sum: ",total(data1))
    sum:  5
    >>> 
    >>> data2 = (44, 78, 90, 80, -1)
    >>> print("sum: ",total(data2))
    Traceback (most recent call last):
      File "<pyshell#24>", line 1, in <module>
        print("sum: ",total(data2))
      File "<pyshell#18>", line 4, in total
        if i < 0: raise NumberError(str(i))
    NumberError: -1:非法数值(<0>>> 
    

    四:断言处理

    用户在编写程序时,在调试阶段往往需要判断代码执行过程中变量的值等信息:

    1. 用户可以使用print()函数打印输出结果
    2. 也可以通过断点跟踪调试查看变量
    3. 但使用断言更加灵活

    assert语句和AssertionError

    断言的声明:

    • assert <布尔表达式>
      即:if __debug__: if not testexpression: raise AssertionError
    • assert <布尔表达式>,<字符串表达式>
      即:if __debug__: if not testexpression: raise AssertionError(data)
      字符串表达式(即data)是断言失败时输出的失败消息

    __debug__也是布尔值,Python解释器有两种:调试模式和优化模式

    • 调试模式:__debug__ == True
    • 优化模式:__debug__ == False

    在学习中,对于执行一个py模块(比如test.py)我们通常在cmd中这么输入python test.py,而这默认是调试模式。
    如果我们要使用优化模式来禁用断言来提高程序效率,我们可以加一个运行选项-O,在控制台中这么输入python -O test.py

    看一下断言的示例吧,理解一下用法:

    a =int(input("a: "))
    b =int(input("b: "))
    assert b != 0, '除数不能为零'
    c = a/b
    print("a/b = ", c)
    

    cmd出场:
    输入正确数值时:

    输入错误数值时:

    禁用断言,并且输入错误数值时:

    案例研究:使用调试器调试Python程序

    https://blog.csdn.net/Zhangguohao666/article/details/103948568

    了解使用Python调试器调试程序的方法

    第八章 函数和函数式编程


    一些知识点总结和几个例题

    Python中函数的分类:

    1. 内置函数
      在程序中可以直接使用
    2. 标准库函数
      Python语言安装程序同时会安装若干标准库,例如math、random等
    3. 第三方库函数
      Python社区提供了许多其它高质量的库,在下载、安装这些库后,通过import语句可以导入库
    4. 用户自定义函数
    • 函数名为有效的标识符(命名规则为全小写字母,可以使用下划线增加可阅读性,例如my_func()
    • 函数可以使用return返回值
      如果函数体中包含return语句,则返回值
      否则不返回,即返回值为空(None),无返回值的函数相当于其它编程语言中的过程

    调用函数之前程序必须先执行def语句,创建函数对象

    • 内置函数对象会自动创建
    • import导入模块时会执行模块中的def语句,创建模块中定义的函数
    • Python程序结构顺序通常为import语句>函数定义>全局代码

    一:产生副作用的函数,纯函数

    打印等腰三角形

    n = int(input("行数:"))
    
    def print_star(n):
        print((" * " * n).center(50))
    
    for i in range(1, 2*n, 2):
        print_star(i)
    

    输出:

    行数:5
                            *                         
                         *  *  *                      
                      *  *  *  *  *                   
                   *  *  *  *  *  *  *                
                *  *  *  *  *  *  *  *  *             
    

    上面代码中的print_star()是一个产生副作用的函数,其副作用是向标准输出写入若干星号

    • 副作用:例如读取键盘输入,产生输出,改变系统的状态等
    • 在一般情况下,产生副作用的函数相当于其它程序设计语言中的过程,可以省略return语句

    定义计算并返回第n阶调和数(1+1/2+1/3+…+1/n)的函数,输出前n个调和数

    def harmonic(n):
        total = 0.0
        for i in range(1, n+1):
            total += 1.0/i
        return total
    
    n = int(input("n:"))
    
    print("输出前n个调和数的值:")
    for i in range(1, n+1):
        print(harmonic(i))
    

    输出:

     n:8
    输出前n个调和数的值:
    1.0
    1.5
    1.8333333333333333
    2.083333333333333
    2.283333333333333
    2.4499999999999997
    2.5928571428571425
    2.7178571428571425         
    

    上面代码中的harmonic()是纯函数

    纯函数:给定同样的实际参数,其返回值唯一,且不会产生其它的可观察到的副作用

    注意:编写同时产生副作用和返回值的函数通常被认为是不良编程风格,但有一个例外,即读取函数。例如,input()函数既可以返回一个值,又可以产生副作用(从标准输入中读取并消耗一个字符串)

    二:传递不可变对象、可变对象的引用

    • 实际参数值默认按位置顺序依次传递给形式参数。如果参数个数不对,将会产生错误

    在调用函数时:

    1. 若传递的是不可变对象(例如:int、float、bool、str对象)的引用,则如果函数体中修改对象的值,其结果实际上是创建了一个新的对象
    i = 1
    
    def func(i,n):
        i += n
        return i
    
    print(i)#1
    func(i,10)
    print(i)#1
    

    执行函数func()后,i依旧为1,而不是11

    1. 若传递的是可变对象(例如:list对象)的引用,则在函数体中可以直接修改对象的值
    import random
    
    def shuffle(a):
        n = len(a)
        for i in range(n):
            r = random.randrange(i,n)
            a[i],a[r] = a[r],a[i]
    
    a = [1,2,3,4,5]
    print("初始:",a)
    shuffle(a)
    print("调用函数后:",a)
    

    输出:

    初始: [1, 2, 3, 4, 5]
    调用函数后: [1, 5, 4, 3, 2]
    

    三:可选参数,命名参数,可变参数,强制命名参数

    可选参数

    • 在声明函数时,如果希望函数的一些参数是可选的,可以在声明函数时为这些参数指定默认值
    >>> def babbles(words, times=1):
    	print(words * times)
    
    	
    >>> babbles('Hello')
    Hello
    >>> 
    >>> babbles("Hello", 2)
    HelloHello
    >>> 
    

    注意到一点:必须先声明没有默认值的形参,然后再声明有默认值的形参,否则报错。 这是因为在函数调用时默认是按位置传递实际参数的。

    怎么理解上面那句话呢?

    默认是按位置传递实际参数(如果有默认值的形参在左边,无默认值的形参在右,那么在调用函数时,你的实参该怎么传递呢?)

    命名参数

    • 位置参数:当函数调用时,实参默认按位置顺序传递形参
    • 命名参数(关键字参数):按名称指定传入的参数
      参数按名称意义明确
      传递的参数与顺序无关
      如果有多个可选参数,则可以选择指定某个参数值

    基于期中成绩和期末成绩,按照指定的权重计算总评成绩

    >>> def my_sum(mid_score, end_score, mid_rate = 0.4):
    	score = mid_score*mid_rate + end_score*(1-mid_rate)
    	print(format(score,'.2f'))
    
    	
    >>> my_sum(80,90)
    86.00
    >>> my_sum(mid_score = 80,end_score = 90)
    86.00
    >>> my_sum(end_score = 90,mid_score = 80)
    86.00
    >>> 
    

    可变参数

    • 在声明函数时,可以通过带星号的参数(例如:def func(* param))向函数传递可变数量的实参,调用函数时,从那一点后所有的参数被收集为一个元组
    • 在声明函数时,可以通过带双星号的参数(例如:def func(** param))向函数传递可变数量的实参,调用函数时,从那一点后所有的参数被收集为一个字典

    利用带星的参数计算各数字的累加和

    >>> def my_sum(a,b,*c):
        total = a+b
        for i in c:
            total += i
        return total
    
    >>> print(my_sum(1,2))
    3
    >>> print(my_sum(1,2,3,4,5,6))
    21
    

    利用带星和带双星的参数计算各数字的累加和

    >>> def my_sum(a,b,*c,**d):
        total = a+b
        for i in c:
            total += i
        for key in d:
            total += d[key]
        return total
    
    >>> print(my_sum(1,2))
    3
    >>> print(my_sum(1,2,3,4))
    10
    >>> print(my_sum(1,2,3,4,male=1,female=2))
    13
    

    强制命名参数

    • 在带星号的参数后面声明参数会导致强制命名参数(Keyword-only),然后在调用时必须显式使用命名参数传递值
    • 因为按位置传递的参数默认收集为一个元组,传递给前面带星号的可变参数
    >>> def my_sum(*, mid_score, end_score, mid_rate = 0.4):
        score = mid_score*mid_rate + end_score*(1-mid_rate)
        print(format(score,'.2f'))
    
    >>> my_sum(mid_score=80,end_score=90)
    86.00
    >>> my_sum(end_score=90,mid_score=80)
    86.00
    >>> my_sum(80,90)
    Traceback (most recent call last):
      File "<pyshell#47>", line 1, in <module>
        my_sum(80,90)
    TypeError: my_sum() takes 0 positional arguments but 2 were given
    >>> 
    

    四:全局语句global示例,非局部语句nonlocal示例,输出局部变量和全局变量

    • 在函数体中可以引用全局变量,但是要为定义在函数外的全局变量赋值,需要使用global语句
    pi = 2.1415926
    e = 2.7182818
    
    def my_func():
        global pi
        pi = 3.14
        print("global pi = ", pi)
        e = 2.718
        print("local e = ", e)
    
    print('module pi = ', pi)
    print('module e = ', e)
    my_func()
    print('module pi = ', pi)
    print('module e = ', e)
    

    输出:

    module pi =  2.1415926
    module e =  2.7182818
    global pi =  3.14
    local e =  2.718
    module pi =  3.14
    module e =  2.7182818
    
    • 在函数体中可以定义嵌套函数,在嵌套函数中如果要为定义在上级函数体的局部变量赋值,可以使用nonlocal
    def outer_func():
        tax_rate = 0.17
        print('outer function tax rate is ',tax_rate)
        def inner_func():
            nonlocal tax_rate
            tax_rate = 0.01
            print('inner function tax rate is ',tax_rate)
        inner_func()
        print('outer function tax rate is ',tax_rate)
    
    outer_func()
    

    输出:

    outer function tax rate is  0.17
    inner function tax rate is  0.01
    outer function tax rate is  0.01
    
    • 输出局部变量和全局变量
    1. 内置函数locals(),局部变量列表
    2. 内置函数globals(),全局变量列表

    五:获取和设置最大递归数

    在sys模块中,函数getrecursionlimit()setrecursionlimit()用于获取和设置最大递归次数

    >>> import sys
    >>> sys.getrecursionlimit()
    1000
    >>> sys.setrecursionlimit(666)
    >>> sys.getrecursionlimit()
    666
    >>> 
    

    六:三个有趣的内置函数:eval()、exec()、compile()

    eval

    • 对动态表达式进行求值,返回值
    • eval(expression, globals=None, locals=None)
      expression是动态表达式的字符串
      globals和locals是求值时使用的上下文环境的全局变量和局部变量,如果不指定,则使用当前运行上下文
    >>> x = 2
    >>> str_func = input("请输入表达式:")
    请输入表达式:x**2+2*x+1
    >>> eval(str_func)
    9
    >>> 
    

    exec

    • 可以执行动态表达式,不返回值
    • exec(str, globals=None, locals=None)
    >>> exec("for i in range(10): print(i, end=' ')")
    0 1 2 3 4 5 6 7 8 9 
    >>> 
    

    compile

    • 编译代码为代码对象,可以提高效率
    • compile(source, filename, mode)
      source为代码语句的字符串;如果是多行语句,则每一行的结尾必须有换行符\n
      filename为包含代码的文件
      mode为编码方式,可以为'exec'(用于语句序列的执行),可以为'eval'(用于表达式求值),可以为'single'(用于单个交互语句)
    >>> co = compile("for i in range(10): print(i, end=' ')", '', 'exec')
    >>> exec(co)
    0 1 2 3 4 5 6 7 8 9 
    >>> 
    

    七:map(),filter()

    • map(f, iterable,…),将函数f应用于可迭代对象,返回结果为可迭代对象

    示例1:

    >>> def is_odd(x):
    	return x%2 == 1
    
    >>> list(map(is_odd,range(5)))
    [False, True, False, True, False]
    >>> 
    

    示例2:

    >>> list(map(abs,[1,-2,3,-4,5,-6]))
    [1, 2, 3, 4, 5, 6]
    >>> 
    

    示例3:

    >>> list(map(str,[1,2,3,4,5]))
    ['1', '2', '3', '4', '5']
    >>
    

    示例4:

    >>> def greater(x,y):
    	return x>y
    
    >>> list(map(greater,[1,5,7,3,9],[2,8,4,6,0]))
    [False, False, True, False, True]
    >>> 
    
    • filter(f, iterable),将函数f应用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素,返回结果为可迭代对象

    示例1(返回个位数的奇数):

    >>> def is_odd(x):
    	return x%2 == 1
    
    >>> list(filter(is_odd, range(10)))
    [1, 3, 5, 7, 9]
    >>> 
    

    示例2(返回三位数的回文):

    >>> list(filter(is_palindrome, range(100, 1000)))
    [101, 111, 121, 131, 141, 151, 161, 171, 181, 191, 202, 212, 222, 232, 242, 252, 262, 272, 282, 292, 303, 313, 323, 333, 343, 353, 363, 373, 383, 393, 404, 414, 424, 434, 444, 454, 464, 474, 484, 494, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 606, 616, 626, 636, 646, 656, 666, 676, 686, 696, 707, 717, 727, 737, 747, 757, 767, 777, 787, 797, 808, 818, 828, 838, 848, 858, 868, 878, 888, 898, 909, 919, 929, 939, 949, 959, 969, 979, 989, 999]
    >>> 
    

    八:Lambda表达式和匿名函数

    匿名函数广泛应用于需要函数对象作为参数、函数比较简单并且只使用一次的场合

    格式:

    lambda arg1,arg2... : <expression>
    

    其中,arg1、arg2等为函数的参数,<expression>为函数的语句,其结果为函数的返回值

    示例1(计算两数之和):

    >>> f = lambda x,y : x+y
    >>> type(f)
    <class 'function'>
    >>> f(1,1)
    2
    >>> 
    

    示例2(返回奇数):

    >>> list(filter(lambda x:x%2==1, range(10)))
    [1, 3, 5, 7, 9]
    >>> 
    

    示例3(返回非空元素):

    >>> list(filter(lambda s:s and s.strip(), ['A', '', 'B', None, 'C', ' ']))
    ['A', 'B', 'C']
    >>> 
    

    补充:

    • strip()用来去除头尾字符、空白符(\n,\r,\t,’’,即换行、回车、制表、空格)
    • lstrip()用来去除开头字符、空白符
    • rstrip()用来去除结尾字符、空白符

    再补充一点:

    • \n到下一行的开头
    • \r回到这一行的开头

    示例4(返回大于0的元素):

    >>> list(filter(lambda x:x>0, [1,0,-2,8,5]))
    [1, 8, 5]
    >>> 
    

    示例5(返回元素的平方):

    >>> list(map(lambda x:x*x, range(10)))
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    >>> 
    

    九:operator模块和操作符函数

    Python内置操作符的函数接口,它定义了对应算术和比较等操作的函数,用于map()、filter()等需要传递函数对象作为参数的场合,可以直接使用而不需要使用函数定义或者Lambda表达式,使得代码更加简洁

    示例1(concat(x,y)对应于x+y):

    >>> import operator
    >>> a = 'hello'
    >>>> operator.concat(a, ' world')
    'hello world'
    

    实例2(operator.gt对应于操作符>):

    >>> import operator
    >>> list(map(operator.gt, [1,5,7,3,9],[2,8,4,6,0]))
    [False, False, True, False, True]
    >>> 
    

    十:functools.reduce(),偏函数functools.partial(),sorted()

    functools.reduce()

    functools.reduce(func, iterable[, iterable[, initializer]])

    • 使用指定的带两个参数的函数func对一个数据集合的所有数据进行下列操作:
    • 使用第一个和第二个数据作为参数用func()函数运算,得到的结果再与第三个数据作为参数用func()函数运算,依此类推,最后得到一个结果
    • 可选的initialzer为初始值

    示例:

    >>> import functools,operator
    >>> functools.reduce(operator.add, [1,2,3,4,5])
    15
    >>> functools.reduce(operator.add, [1,2,3,4,5], 10)
    25
    >>> functools.reduce(operator.add, range(1,101))
    5050
    >>> 
    >>> functools.reduce(operator.mul, range(1,11))
    3628800
    

    偏函数functools.partial()

    functools.partial(func, *arg, **keywords)

    • 通过把一个函数的部分参数设置为默认值的方式返回一个新的可调用(callable)的partial对象
    • 主要用于设置预先已知的参数,从而减少调用时传递参数的个数

    示例(2的n次方):

    >>> import functools,math
    >>> pow2 = functools.partial(math.pow, 2)
    >>> list(map(pow2, range(11)))
    [1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0]
    >>> 
    

    十一:sorted()

    sorted(iterable, *, key=None, reverse=False)

    • iterable是待排序的可迭代对象
    • key是比较函数(默认为None,按自然顺序排序)
    • reverse用于指定是否逆序排序

    示例1(数值。默认自然排序):

    >>> sorted([1,6,4,-2,9])
    [-2, 1, 4, 6, 9]
    >>> sorted([1,6,4,-2,9], reverse=True)
    [9, 6, 4, 1, -2]
    >>> sorted([1,6,4,-2,9], key=abs)
    [1, -2, 4, 6, 9]
    

    示例2(字符串,默认按字符串字典序排序):

    >>> sorted(['Dod', 'cat', 'Rabbit'])
    ['Dod', 'Rabbit', 'cat']
    >>> sorted(['Dod', 'cat', 'Rabbit'], key=str.lower)
    ['cat', 'Dod', 'Rabbit']
    >>> sorted(['Dod', 'cat', 'Rabbit'], key=len)
    ['Dod', 'cat', 'Rabbit']
    

    示例3(元组,默认按元组的第一个元素排序):

    >>> sorted([('Bob', 75), ('Adam', 92), ('Lisa', 88)])
    [('Adam', 92), ('Bob', 75), ('Lisa', 88)]
    >>> sorted([('Bob', 75), ('Adam', 92), ('Lisa', 88)], key=lambda t:t[1])
    [('Bob', 75), ('Lisa', 88), ('Adam', 92)]
    

    十二:函数装饰器

    这玩意就很有意思了,很Java语言中的注解是很相像的

    示例1:

    import time,functools
    
    def timeit(func):
        def wrapper(*s):
            start = time.perf_counter()
            func(*s)
            end = time.perf_counter()
            print('运行时间:', end - start)
        return wrapper
    
    @timeit
    def my_sum(n):
        sum = 0
        for i in range(n): sum += i
        print(sum)
    
    if __name__ == '__main__':
        my_sum(10_0000)
    

    结果:

    4999950000
    运行时间: 0.013929100000000028
    

    怎么理解上面的代码呢?

    • 首先,timeit()返回的是wrapper,而不是执行(没有小括号)
    • @timeit相当于,在调用my_sum()的前一刻,会执行这么个语句:my_sum = timeit(my_sum)

    示例2:

    def makebold(fn):
        def wrapper(*s):
            return "<b>" + fn(*s) + "</b>"
        return wrapper
    
    def makeitalic(fn):
        def wrapper(*s):
            return "<i>" + fn(*s) + "</i>"
        return wrapper
    
    @makebold
    @makeitalic
    def htmltags(str1):
        return str1
    
    print(htmltags('Hello'))
    
    

    输出:

    <b><i>Hello</i></b>
    

    选择题:1~5

    1

    >>> print(type(lambda:None))
    <class 'function'>
    

    2

    >>> f = lambda x,y:x*y
    >>> f(12, 34)
    408
    

    3

    >>> f1 = lambda x:x*2
    >>> f2 = lambda x:x**2
    >>> print(f1(f2(2)))
    8
    

    4

    >>> def f1(p, **p2):
    	print(type(p2))
    
    	
    >>> f1(1, a=2)
    <class 'dict'>
    

    5

    >>> def f1(a,b,c):
    	print(a+b)
    
    	
    >>> nums = (1,2,3)
    >>> f1(*nums)
    3
    

    思考题:4~11

    4

    >>> d = lambda p:p*2
    >>> t = lambda p:p*3
    >>> x = 2
    >>> x = d(x)
    >>> x = t(x)
    >>> x = d(x)
    >>> print(x)
    24
    

    5

    >>> i = map(lambda x:x**2, (1,2,3))
    >>> for t in i:
    	print(t, end=' ')
    
    	
    1 4 9 
    

    6

    >>> def f1():
    	"simple function"
    	pass
    
    >>> print(f1.__doc__)
    simple function
    

    7

    >>> counter = 1
    >>> num = 0
    >>> def TestVariable():
    	global counter
    	for i in (1, 2, 3) : counter += 1
    	num = 10
    
    	
    >>> TestVariable()
    >>> print(counter, num)
    4 0
    

    8

    >>> def f(a,b):
    	if b==0 : print(a)
    	else : f(b, a%b)
    
    	
    >>> print(f(9,6))
    3
    None
    

    求最大公约数

    9

    >>> def aFunction():
    	"The quick brown fox"
    	return 1
    
    >>> print(aFunction.__doc__[4:9])
    quick
    

    10

    >>> def judge(param1, *param2):
    	print(type(param2))
    	print(param2)
    
    	
    >>> judge(1, 2, 3, 4, 5)
    <class 'tuple'>
    (2, 3, 4, 5)
    

    11

    >>> def judge(param1, **param2):
    	print(type(param2))
    	print(param2)
    
    	
    >>> judge(1, a=2, b=3, c=4, d=5)
    <class 'dict'>
    {'a': 2, 'b': 3, 'c': 4, 'd': 5}
    

    上机实践:2~5

    2. 编写程序,定义一个求阶乘的函数fact(n),并编写测试代码,要求输入整数n(n>=0)。请分别使用递归和非递归方式实现

    递归方式:

    def fact(n):
        if n == 0 :
            return 1
        return n*fact(n-1)
    
    n = int(input("请输入整数n(n>=0):"))
    print(str(n)+" ! =  " + str(fact(n)))
    
    

    非递归方式:

    def fact(n):
        t = 1
        for i in range(1,n+1):
            t *= i
        return t
    
    n = int(input("请输入整数n(n>=0):"))
    print(str(n)+" ! =  " + str(fact(n)))
    
    

    输出:

    请输入整数n(n>=0):5
    5 ! =  120
    

    3. 编写程序,定义一个求Fibonacci数列的函数fib(n),并编写测试代码,输出前20项(每项宽度5个字符位置,右对齐),每行输出10个。请分别使用递归和非递归方式实现

    递归方式:

    def fib(n):
        if (n == 1 or n == 2):
            return 1
        return fib(n-1)+fib(n-2)
    
    for i in range(1,21):
        print(str(fib(i)).rjust(5,' '),end = ' ')
        if i %10 == 0:
            print()
    

    非递归方式:

    def fib(n):
        if (n == 1 or n == 2):
            return 1
        n1 = n2 = 1
        for i  in range(3,n+1):
            n3 = n1+n2
            n1 = n2
            n2 = n3
        return n3
    
    for i in range(1,21):
        print(str(fib(i)).rjust(5,' '),end = ' ')
        if i %10 == 0:
            print()
    

    输出:

        1     1     2     3     5     8    13    21    34    55
       89   144   233   377   610   987  1597  2584  4181  6765
    

    4. 编写程序,利用可变参数定义一个求任意个数数值的最小值的函数min_n(a,b,*c),并编写测试代码。例如对于“print(min_n(8, 2))”以及“print(min_n(16, 1, 7, 4, 15))”的测试代码

    def min_n(a,b,*c):
        min_number = a if(a < b) else b
        for n in c:
            if n < min_number:
                min_number = n
        return min_number
    
    print(min_n(8, 2))
    print(min_n(16, 1, 7, 4, 15))
    

    输出:

    2
    1
    

    5. 编写程序,利用元组作为函数的返回值,求序列类型中的最大值、最小值和元素个数,并编写测试代码,假设测试代码数据分别为s1=[9, 7, 8, 3, 2, 1, 55, 6]、s2=[“apple”, “pear”, “melon”, “kiwi”]和s3="TheQuickBrownFox"

    def func(n):
        return (max(n),min(n),len(n))
        
    s1=[9, 7, 8, 3, 2, 1, 55, 6]
    s2=["apple", "pear", "melon", "kiwi"]
    s3="TheQuickBrownFox"
    
    for i in (s1,s2,s3):
        print("list = ", i)
        t = func(i)
        print("最大值 = {0},最小值 = {1},元素个数 = {2}".format(t[0], t[1], t[2]))
    

    输出:

    list =  [9, 7, 8, 3, 2, 1, 55, 6]
    最大值 = 55,最小值 = 1,元素个数 = 8
    list =  ['apple', 'pear', 'melon', 'kiwi']
    最大值 = pear,最小值 = apple,元素个数 = 4
    list =  TheQuickBrownFox
    最大值 = x,最小值 = B,元素个数 = 16
    

    案例研究:井字棋游戏

    https://blog.csdn.net/Zhangguohao666/article/details/103280740

    了解Python函数的定义和使用


    由于本文的内容太多了,导致了两个很不好的结果,
    一是:在网页中打开本篇博客的加载时间太长了,明显的卡顿很影响阅读体验;
    二是:本人在对本篇文章进行更新或者修改内容时,卡的要死。
    遂,
    将本文第八章后面的很多内容拆分到新的文章中,望大家理解


    第九章 面向对象的程序设计


    第十章 模块和客户端


    第十一章 算法与数据结构基础


    第十二章 图形用户界面


    我对图形用户界面基本无兴趣,无特殊情况,基本不打算碰这方面内容

    案例研究:简易图形用户界面计算器

    第十三章 图形绘制


    与上一章相同,我对于图形绘制的兴趣也基本没有,尝试做了2-7题,就完全没兴趣做下去了

    图形绘制模块:tkinter

    2. 参考例13.2利用Canvas组件创建绘制矩形的程序,尝试改变矩形边框颜色以及填充颜色

    from tkinter import *
    
    root = Tk()
    c = Canvas(root, bg = 'white', width = 130, height = 70)
    c.pack()
    
    c.create_rectangle(10, 10, 60, 60, fill = 'red')
    c.create_rectangle(70, 10, 120, 60, fill = 'green', outline = 'blue', width = 5)
    
    

    创建画布对象:

    • root = Tk()
      创建一个Tk根窗口组件root
    • c = Canvas(root, bg = 'white', width = 130, height = 70)
      创建大小为200 * 100、背景颜色为白色的画布
    • c.pack()
      调用组件pack()方法,调整其显示位置和大小

    绘制矩形:

    c.create_rectangle(x0, y0, x1, y1, option, ...)
    
    • (x0,y0)是左上角的坐标
    • (x1,y1)是右下角的坐标
    • c.create_rectangle(70, 10, 120, 60, fill = 'green', outline = 'blue', width = 5)
      用蓝色边框、绿色填充矩形,边框宽度为5

    3. 参考例13.3利用Canvas组件创建绘制椭圆的程序,尝试修改椭圆边框样式、边框颜色以及填充颜色

    from tkinter import *
    
    root = Tk()
    c = Canvas(root, bg = 'white', width = 280, height = 70)
    c.pack()
    
    c.create_oval(10, 10, 60, 60, fill = 'green')
    c.create_oval(70, 10, 120, 60, fill = 'green', outline = 'red', width = 5)
    c.create_oval(130, 25, 180, 45, dash = (10,))
    c.create_oval(190, 10, 270, 50, dash = (1,), width = 2)
    
    

    绘制椭圆

    c.create_oval(x0, y0, x1, y1, option, ...)
    
    • (x0,y0)是左上角的坐标
    • (x1,y1)是右下角的坐标
    • c.create_oval(70, 10, 120, 60, fill = 'green', outline = 'red', width = 5)
      绿色填充、红色边框,宽度为5
    • c.create_oval(130, 25, 180, 45, dash = (10,))
      虚线椭圆

    4. 参考例13.4利用Canvas组件创建绘制圆弧的程序,尝试修改圆弧样式、边框颜色以及填充颜色

    from tkinter import *
    
    root = Tk()
    c = Canvas(root, bg = 'white', width = 250, height = 70)
    c.pack()
    
    c.create_arc(10, 10, 60, 60, style = ARC)
    c.create_arc(70, 10, 120, 60, style = CHORD)
    c.create_arc(130, 10, 180, 60, style = PIESLICE)
    for i in range(0, 360, 60):
        c.create_arc(190, 10, 240, 60, fill = 'green', outline = 'red', start = i, extent = 30)
    
    

    绘制圆弧:

    c.create_arc(x0, y0, x1, y1, option, ...)
    
    • (x0,y0)是左上角的坐标
    • (x1,y1)是右下角的坐标
    • 选项start(开始角度,默认为0)和extend(圆弧角度,从start开始逆时针旋转,默认为90度)决定圆弧的角度范围
    • 选项start用于设置圆弧的样式

    5. 参考例13.5利用Canvas组件创建绘制线条的程序,尝试修改线条样式和颜色

    from tkinter import *
    
    root = Tk()
    c = Canvas(root, bg = 'white', width = 250, height = 70)
    c.pack()
    
    c.create_line(10, 10, 60, 60, arrow = BOTH, arrowshape = (3, 4, 5))
    c.create_line(70, 10, 95, 10, 120, 60, fill = 'red')
    c.create_line(130, 10, 180, 10, 130, 60, 180, 60, fill = 'green', width = 10, arrow = BOTH, joinstyle = MITER)
    c.create_line(190, 10, 240, 10, 190, 60, 240