Skip to content

01 理解类和对象

一、创建类和实例化对象

1. 怎么创建类

使用关键字class ,并且类名要大写;紧接着更上的是构造函数__init__只要实例化这个类就会自动运行。构造函数后面是自定义函数。

class Person:
    def __init__(self,name):
        self.name = name
    def say_hello(self):
        print("打招呼","大家好,我叫:"+self.name)
除了以上这种创建类的方法外,通常我们还见到以下创建类的方法:
class Person(object):
    def __init__(self,name):
        self.name = name
    def say_hello(self):
        print("打招呼","大家好,我叫:"+self.name)
小括号内加上object,这在我们后面介绍类的继承的时候会具体讲解,这里的小括号表示继承object类。Python中所有的类都继承这个叫object的根类,这个object也可以省略,表示默认继承object类。
class Person:
    """
    Person是描述人的基本类:包含了姓名性别、出生日期、手机、邮箱、地址
    """
    def __init__(self,name,gender,birthday,mobile,email,address):
        """
        构造函数:用来初始化类的静态特征。在实例化的时候自动运行
        :param name: 姓名
        """
        self.name = name
        self.gender = gender
        self.birthday = birthday
        self.mobile = mobile
        self.email = email
        self.address = address

    def say_hello(self):
        """
        打招呼的方法,类的动态特征
        :return:
        """
        print("打招呼","大家好,我叫:"+self.name)

if __name__ == "__main__":
    alice = Person("Alice","女","1998-10-22","13878345893","1232987@qq.com","北京市朝阳区")
    # 访问静态属性:对象名.静态属性名
    print(alice.mobile)
    # 访问动态属性:对象名.动态属性名()
    alice.say_hello()

2. 读取类的信息

(1)访问类的名称:类名.__name__ (2)访问类的描述信息:类名.__doc__ (3)访问类的方法的描述信息:类名.方法名.__doc__ (4)访问类的字典属性:类名.__dict__ (5)访问实例对应的类:类名.__class__

3. 总结:关于类和对象

类:把一类事物具有对象的静态特征和动态特征的抽象表达; 对象:是特征与技能的结合体,其中特征和技能分别对应对象的数据属性和方法属性。

二、面向对象的思维开发简单计算器

我们先用面向过程的思维开发一款简单的计算器:

if __name__ == "__main__":
    num01 = int(input("请输入第一个整数:"))
    action = input("请选择要执行的操作【加+、减-、乘*、除/、求余%】:")
    num02 = int(input("请输入第一个整数:"))
    if action == "+":
        print("%d + %d = %d"%(num01,num02,num01+num02))
    elif action == "-":
        print("%d - %d = %d" % (num01, num02, num01 - num02))
    elif action  == "*":
        print("%d * %d = %d" % (num01, num02, num01 * num02))
    elif action == "/":
        print("%d / %d = %.2f" % (num01, num02, num01 / num02))
    elif action == "%":
        print(str(num01)+ "%" +str(num02)+"="+str(num01%num02))
    else:
        print("您的输入有误")
输出结果: 2.gif

虽然代码很简洁、但是很难复用; 所以我们转为面向对象的思维的开发: 我们建一个calclass.py的类,用于计算器的计算:

class Calculator:
    def __init__(self,num01,num02,action=""):  # 这里action预设为空值,表示兼容只传两个参数的情况
        self.num01 = int(num01)
        self.num02 = int(num02)
        self.action = action
    def get_result(self):
        if "+" in self.action:
            return self.add()
        if "-" in self.action:
            return self.sub()
        if "*" in self.action:
            return self.mul()
        if "/" in self.action:
            return self.div()
        if "%" in self.action:
            return self.yu()

    def add(self):
        return self.num01 + self.num02
    def sub(self):
        return self.num01 - self.num02
    def mul(self):
        return self.num01 * self.num02
    def div(self):
        return self.num01 / self.num02
    def yu(self):
        return  self.num01 % self.num02

    def print_result(self,action:str,result):
        print(str(self.num01)+" "+action+" "+str(self.num02)+" = "+str(result))
然后再创建一个计算器的布局文件:
from tkinter import *
from tkinter.ttk import *
from tkinter.messagebox import *

import calclass

# 整个窗体的GUI就是一个类
class Calculator:
    def __init__(self):
        self.frame = Tk()
        self.frame.title("计算器")
        self.frame.geometry("560x120+300+250")
        self.frame.resizable(0,0)
        # self.frame["bg"] = "darkgray"

        self.style01 = Style()
        self.style01.configure("TButton",font=("微软雅黑",14,"bold"))

        # 添加一个文本输入框
        self.var_num01 = StringVar()
        self.Entry_num01 = Entry(self.frame,textvariable = self.var_num01,font = ("微软雅黑",14,"bold"),width = 10)
        self.Entry_num01.place(x=10,y=40)

        # 添加一个下拉框的运算符
        self.var_action = StringVar()
        self.ComboBox_action = Combobox(self.frame,font = ("微软雅黑",14,"bold"),textvariable = self.var_action,width = 6)
        self.ComboBox_action["values"] = ["加【+】","减【-】","乘【*】","除【/】","余【%】"]
        self.ComboBox_action["state"] = "readonly"
        self.ComboBox_action.current(0)
        # self.ComboBox_action.bind("<<ComboboxSelected>>",self.sel_operator)
        self.ComboBox_action.place(x = 120,y = 40)

        # 添加一个文本输入框 --num02
        self.var_num02 = StringVar()
        self.Entry_num02 = Entry(self.frame, textvariable = self.var_num02,font=("微软雅黑", 14, "bold"), width=10)
        self.Entry_num02.place(x=210, y=40)

        # 添加一个Label标签 --Label
        self.Label_result = Label(self.frame,text = "=",font=("微软雅黑", 14, "bold"))
        self.Label_result.place(x = 320,y = 43)

        # 添加一个文本输入框 --result
        self.var_result = StringVar()
        self.Entry_result = Entry(self.frame, textvariable = self.var_result,state=DISABLED,font=("微软雅黑", 14, "bold"), width=10)
        self.Entry_result.place(x=340, y=40)

        # 显示计算按钮
        self.Button_cal = Button(self.frame,style = "TButton",text = "计算",command = self.number_cal)
        self.Button_cal.place(x=450,y=43)

    def number_cal(self):
        num01 = self.var_num01.get()
        num02 = self.var_num02.get()
        action = self.var_action.get()
        my_cal = calclass.Calculator(num01,num02,action)
        self.var_result.set(my_cal.get_result())

    def show(self):
        self.frame.mainloop()

if __name__ == '__main__':
    my_calculator = Calculator()
    my_calculator.show()
效果演示: 1.gif

虽然在这里,使用面向对象开发的方式写的代码看上去要比直接面向过程的方式要复杂一些,但是使用面向对象进行封装后面的代码可以多次复用,面向对象的优势就体现出来了。

三、类和对象的内存分配

对象(实例)本身只有数据(静态)属性,但是Python的class机制会将函数(动态)绑定到对象上,称为对象的方法,或者叫绑定方法。

四、self关键字

在Python面向对象的代码中,self关键字出现的频率非常高,它究竟代表了什么意思呢?

self 本质就是一个指针,指向当前对象所占内存空间的一个指针,同C#、Java中的this关键字

五、实现构造函数的“重载”

重载的含义是:方法名相同,参数个数不同; java、C#都具备重载的特性,但是Python没有,那么在构造对象的时候,参数的个数不足构造函数的参数个数该怎么办呢? 解决这个问题的办法有两个:

1.给类的构造函数设置默认值

通常设为""空,表明在构造对象时,如果提供了参数就使用提供的参数,如果没有提供参数就使用默认的空值,这样构造对象时就不会报错。

class Person:
    def __init__(self,name="",gender="",age="",mobile="",email="",address=""):
        self.name = name
        self.gender = gender
        self.age = age
        self.mobile = mobile
        self.email = email
        self.address = address

    def say_hello(self):
        print("大家好,我是"+self.name+"!希望大家支持我!")

if __name__ == "__main__":
    # ====== alice ========
    alice = Person("Alice","男","23","13771789878","12344@qq.com","北京市海淀区")
    print(alice.address)
    alice.say_hello()
    # ====== bob =========
    bob = Person("Bob","男")
    print(bob.address)
    bob.say_hello()

2.构造函数使用不定长参数

不定长参数使用*开头,一般设置为*args,在构造函数的静态属性赋值的时候设置一个初始值; ```

class Person: def init(self,*args): self.name = "" self.gender = "" self.age = "" self.mobile = "" self.email = "" self.address = "" if len(args) == 0: return elif len(args) == 1: self.name = args[0] elif len(args) == 2: self.name = args[0] self.gender = args[1] elif len(args) == 3: self.name = args[0] self.gender = args[1] self.age = args[2] elif len(args) == 4: self.name = args[0] self.gender = args[1] self.age = args[2] self.mobile = args[3] elif len(args) == 5: self.name = args[0] self.gender = args[1] self.age = args[2] self.mobile = args[3] self.email = args[4] elif len(args) == 6: self.name = args[0] self.gender = args[1] self.age = args[2] self.mobile = args[3] self.email = args[4] self.address = args[5]

def say_hello(self):
    print("大家好,我是"+self.name+"!希望大家支持我!")

if name == "main": # ====== alice ======== alice = Person("Alice","男","23","13771789878","12344@qq.com","北京市海淀区") print(alice.address) alice.say_hello() # ====== bob ========= bob = Person("Bob","男") print(bob.address) bob.say_hello() # ===== peter ======== peter = Person("peter") peter.say_hello() ```exidddsds