current position:Home>Python Learning Chapter 4 Object-Oriented Design

Python Learning Chapter 4 Object-Oriented Design

2022-11-08 07:24:161 meter 8 in the dream


第一章 函数、模块、包
第二章 数据类型
第三章 控制结构
第五章 图形界面设计

第四章 面向对象设计

1 定义和使用类

1.1 定义类

  每个对象都有一个类型,A class is a template for creating object instances,is a generalization of the object,它包含对所创建对象的属性描述和行为特征的定义,相当于一个模板.

  Object properties that are represented as variables when a class is created are called data members or properties(成员变量),用函数形式表示的对象行为称为成员函数(成员方法),成员属性和成员方法统称为类的成员.

格式:

class 类名:
	属性(成员变量)
	属性
	...
	成员函数
# 定义Person类
class Person:
    num = 1
    def SayHello(self):
        print('Hello!')

类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self.

1.2 创建对象

对象是类的实例,After defining the concrete object,可以通过“对象名.成员”Access a data member or member method within it.

对象名 = 类名

p = Person()
p.SayHello()

2 构造函数__init__()

  类有一个名为 _ _ init _ _() 的特殊方法(构造方法,以两个下划线开头和结束),该方法在类实例化时会自动调用.

  Constructors are generally used to set initial values ​​of object data members or perform other necessary initialization work.The user didn't touch the constructor,PythonA default constructor will be provided.

class Complex:
    def __init__(self,realpart,imagpart):
        self.r = realpart
        self.i = imagpart
x = Complex(3.0,-4.5) #类实例化,会自动调用 __init__() 方法
print(x.r,x.i)

运行结果:
在这里插入图片描述

3 析构函数__del__()

  用来释放对象占用的资源,Called automatically when the object is destroyed,使用del删除,That is, the object is destroyed

class Complex:
    def __init__(self,realpart,imagpart):
        self.r = realpart
        self.i = imagpart
    def __del__(self):
        print("Complex不存在")
x = Complex(3.0,-4.5)
print(x.r,x.i)
print(x)
del x  

在这里插入图片描述
在执行“del x”语句后,系统自动调用析构函数,输出“Complex不存在”

4 实例属性和类属性

实例属性:在构造函数__init__()中定义的,定义时以self作为前缀;

类属性:在类中(方法之外)定义的属性.

在主程序中(类的外部),实例属性属于实例(对象),Can only be accessed by object name;

类属性属于类,可以通过类名访问,也可以通过对象名访问,为类的所有实例共享.

class Person:
    num = 1     #类属性(类变量)
    def __init__(self,str,n):   #构造方法
        self.name = str     #实例属性
        self.age = n
    def SayHello(self):      #成员方法(成员函数) 
        print("Hello!")
    def PrintName(self):
        print("姓名:",self.name,'年龄:',self.age)
    def PrintNum(self):
        print('num:',Person.num)
        
P1 = Person("Andy",22)
P2 = Person("Lily",23)

P1.PrintNum()
print(P1.name)      #对象访问实例变量name
P1.PrintName()

P2.PrintNum()
print(P2.name)
P2.PrintName()

Person.num = 2      #修改类属性
print('num:',Person.num)        #类访问类变量num

在这里插入图片描述
You can also dynamically add members to classes and objects

5 私有成员和公有成员

  1. PythonThere is no strict access mechanism for private members.
  2. 在定义类的属性时,如果属性名以两个下划线开头,表示私有属性,否则是公有属性.
  3. 私有属性在类的外部不能直接访问,需要通过调用对象的公有成员方法来访问,或者通过Python支持的特殊方式来访问
  4. Python提供了访问私有属性的特殊方式,可用于程序的测试和调试,The same is true for member methods

对象名._类名+私有成员

Private properties are properties for data encapsulation and confidentiality,一般只能在类的成员方法(类的内部)中使用访问,Direct access to private members of a class from outside is not recommended.

class Car:
    price = 100000      #定义类属性
    def __init__(self,c,w):     #构造方法
        self.color = c      #定义公有属性color
        self.__weight = w   #定义私有属性__weight
car1 = Car('Red',10.5)
print(car1.color)
print(car1._Car__weight)
print(car1.__weight)    
#AttributeError: 'Car' object has no attribute '__weight'

在这里插入图片描述

6 方法

self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数.

self代表类的实例,而非类,类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self.

  1. 公有方法:Can only be called after instantiation
  2. 私有方法:只能在类的内部调用 ,不能在类的外部调用,Private method definitions are the same as private property definitions,在方法前面加上’__'Double underscore is fine;
  3. 静态方法:相当于"全局函数",可以被类直接调用,Can be shared by all instantiated objects,通过staticmethod()Defining static methods does not"self"语句
    例:
#%%方法
class Fruit:
    price = 0   #类变量
    def __init__(self):     #构造方法
        self.__color = 'Red'    #Define and set private propertiescolor
        self.__city = 'Gansu'   
    def __outputColor(self):     #定义私有方法
        print(self.__color)     #访问私有属性color
    def __outputCity(self):
        print(self.__city)
    def output(self):       #定义公有方法output()
        self.__outputColor()    #调用私有方法
        self.__outputCity()
    @ staticmethod
    def getPrice():         #定义静态方法getPrice()
        return Fruit.price
    @ staticmethod
    def setPrice(p):
        Fruit.price = p

7 继承

子类(派生类 DerivedClassName)会继承父类(基类 BaseClassName)的属性和方法.

格式:

class 派生类名(基类名):
  派生成员

BaseClassName(实例中的基类名)必须与派生类定义在一个作用域内.除了类,还可以用表达式,基类定义在另一个模块中时这一点非常有用:

class 派生类名(模块名.基类名):

方法重写必须出现在继承中,Refers to after the derived class inherits the methods of the base class,如果基类方法的功能不能满足需求,需要对基类中的某些方法进行修改.

Python继承中的特点:

  1. The constructor of the base class is not called automatically in inheritance,It needs to be called specifically in the construction of its derived class
  2. 通过“基类名.方法名()”,在派生类中调用基类的方法,且需要带上self参数变量,也可以使用内置函数super()
  3. PythonAlways look for the method of the corresponding type first,If not found in the derived class,Just start to search one by one in the base class.

例1:

class people:
    name = ''   #定义类变量
    age = 0    
    __weight = 0    #定义私有属性,私有属性在类外部无法直接进行访问
    def __init__(self,n,a,w):   #定义构造方法
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁." %(self.name,self.age))
        
        
class student(people):
    grade = ''
    def __init__(self,n,a,w,g):
        #调用父类的构函
        people.__init__(self,n,a,w)
        self.grade = g
    #重写父类的方法
    def speak(self):
        print("%s 说: 我 %d 岁了,我在读 %d 年级"
              %(self.name,self.age,self.grade))
 
s = student('ken',10,60,3)
s.speak()

在这里插入图片描述

例2:

import types
class Person(object):   #基类必须继承于object,否则在派生类中将无法使用super()函数
    def __init__(self,name = '',age = 20,sex = 'man'):
        self.setName(name)
        self.setAge(age)
        self.setSex(sex)
    def setName(self,name):
        if type(name)!=str:
            print('姓名必须是字符串')
            return
        self.__name=name
    def setAge(self,age):
        if type(age)!=int:
            print('年龄必须是数字')
            return
        self.__age = age
    def setSex(self,sex):
        if sex!='男'and sex!='女':
            print('性别输入错误')
            return
        self.__sex=sex
    def show(self):
        print('姓名:',self.__name,'年龄:',self.__age,'性别:',self.__sex)
        


class Student(Person):
    def __init__(self,name='',age=20,sex='man',schoolyear=2016):
        super(Student,self).__init__(name,age,sex)
        #Person.__init__(self,name,age,sex)
        self.setSchoolyear(schoolyear)
    def setSchoolyear(self,schoolyear):
        self.__schoolyear = schoolyear
    def show(self):
        Person.show(self)
        #super(Student,self).show()
        print('入学年份:',self.__schoolyear)
        
        

zhangsan=Person('张三',19,'男')
zhangsan.show()
zhangsan.setAge(22)
zhangsan.show()

lisi=Student('李四',18,'男',2015)
lisi.show()

lisi.setAge(20)
lisi.show()

在这里插入图片描述

8 多态

开闭原则,对扩展开放,对修改封闭
An inherited class from a base class,Its type belongs to this derived class,Also belongs to the base class

9 案例——扑克牌发牌程序

四名牌手打牌,计算机随机将52张牌(不含大小王)发给4players,并在屏幕上显示每players的牌

class Card():
    """ A playing card. """
    RANKS = ["A", "2", "3", "4", "5", "6", "7",
             "8", "9", "10", "J", "Q", "K"]     #牌面数字 1--13
    SUITS = ["梅", "方", "红", "黑"]            #梅为梅花,方为方钻,红为红心,黑为黑桃 

    def __init__(self, rank, suit, face_up = True):
        self.rank = rank                #指的是牌面数字 1--13
        self.suit = suit                #suit指的是花色 
        self.is_face_up = face_up       #是否显示牌正面,True为正面,False为牌背面

    def __str__(self): #print()
        if self.is_face_up:
            rep = self.suit + self.rank #+" "+ str(self.pic_order()) 
        else:
            rep = "XX"
        return rep

    def flip(self):                     #翻牌方法
        self.is_face_up = not self.is_face_up
        
    def pic_order(self):                #牌的顺序号
        if self.rank=="A":
            FaceNum=1
        elif self.rank=="J":
            FaceNum=11       
        elif self.rank=="Q":
            FaceNum=12
        elif self.rank=="K":
            FaceNum=13
        else:
            FaceNum=int(self.rank) 
        if self.suit=="梅":
            Suit=1
        elif self.suit=="方":
            Suit=2
        elif self.suit=="红":
            Suit=3
        else:
            Suit=4
        return (Suit - 1) * 13 + FaceNum
      
class Hand( ):
    """ A hand of playing cards. """
    def __init__(self):
        self.cards = []

    def __str__(self):               #重写print()方法
        if self.cards:
           rep = ""
           for card in self.cards:
               rep += str(card) + "\t"
        else:
            rep = "无牌"
        return rep

    def clear(self):
        self.cards = []

    def add(self, card):
        self.cards.append(card)

    def give(self, card, other_hand):
        self.cards.remove(card)
        other_hand.add(card)

class Poke(Hand):
    """ A deck of playing cards. """
    def populate(self):                     #生成一副牌
        for suit in Card.SUITS:
            for rank in Card.RANKS: 
                self.add(Card(rank, suit))

    def shuffle(self):                      #洗牌
        import random
        random.shuffle(self.cards)          #打乱牌的顺序

    def deal(self, hands, per_hand = 13):    #发牌,发给玩家,每人默认13张牌 
        for rounds in range(per_hand):
            for hand in hands:
                
                    top_card = self.cards[0]
                    self.cards.remove(top_card)
                    hand.add(top_card)
               



if __name__ == "__main__":
    print("This is a module with classes for playing cards.")
    #四个玩家
    players = [Hand(),Hand(),Hand(),Hand()]
    poke1 = Poke()
    poke1.populate()                #生成一副牌
    poke1.shuffle()                 #洗牌
    poke1.deal(players,13)          #发给玩家每人13张牌
    #显示4players的牌
    n=1
    for hand in players:
        print("牌手",n ,end=":")
        print(hand)
        n=n+1

在这里插入图片描述

copyright notice
author[1 meter 8 in the dream],Please bring the original link to reprint, thank you.
https://en.pythonmana.com/2022/312/202211080718078626.html

Random recommended