Python基础:第020课——Color类与文字绘制

Posted 蔚蓝慕

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python基础:第020课——Color类与文字绘制相关的知识,希望对你有一定的参考价值。

视频

观看视频

pygame.Color

Pygame 中用于描述颜色的对象。

Color(name) -> Color,例如:Color("gray")

Color(r, g, b, a) -> Color,例如:Color(190, 190, 190, 255)

Color(rgbvalue) -> Color,例如:Color("#BEBEBEFF")

w3schools颜色选择器,选择任何你想要的颜色,你可以在这里找到它

Pygame 使用 Color 类表示 RGBA 颜色值,每个颜色值的取值范围是 0 ~ 255。当没有给出 alpha 的值时,默认是 255(不透明)

“RGB值”可以是一个颜色名,一个 html 颜色格式的字符串,一个 16 进制数的字符串,或者一个整型像素值。HTML 格式是 #rrggbbaa,其中 “rr”,“gg”,“bb”,“aa” 都是 2 位的 16 进制数。代表 alpha 的 “aa” 是可选的。16 进制数的字符串组成形式为 0xrrggbbaa,当然,其中的 “aa” 也是可选的
下列程序可以列出pygame预定义的颜色

from pprint import pprint
import pygame as pg
pprint(pg.color.THECOLORS)

方法 & 属性

  • pygame.Color.r — 获取或设置 Color 对象的红色值
    pygame.Color.g — 获取或设置 Color 对象的绿色值
    pygame.Color.b — 获取或设置 Color 对象的蓝色值
    pygame.Color.a — 获取或设置 Color 对象的 alpha 值,透明度
    pygame.Color.cmy — 获取或设置 Color 对象表示的 CMY 值
    pygame.Color.hsva — 获取或设置 Color 对象表示的 HSVA 值
    pygame.Color.hsla — 获取或设置 Color 对象表示的 HSLA 值
    pygame.Color.i1i2i3 — 获取或设置 Color 对象表示的 I1I2I3 值
    pygame.Color.normalize() — 返回 Color 对象的标准化 RGBA 值
    pygame.Color.correct_gamma() — 应用一定的伽马值调整 Color 对象
    pygame.Color.set_length() — 设置 Color 对象的长度(成员数量)

示例

让窗口的背景不断变化

import pygame, sys
pygame.init()
screen_size = 640, 480
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption("pygame颜色")
GOLD = (255,251,0)
RED = pygame.Color('red')
WHITE = (255, 255, 255)
GREEN = pygame.Color('green')
color_list = [GOLD,RED,WHITE,GREEN]
fclock = pygame.time.Clock()
running = True
i = 0
while running:
	fclock.tick(1)
	for e in pygame.event.get():
		if e.type == pygame.QUIT:
			running = False
	
	i = i + 1
	i = 0 if i > 3 else i
	
	screen.fill(color_list[i])
	pygame.display.flip()
pygame.quit()
	

Rect对象与Surface对象区别

pygame.Surface表示绘制层、或绘图平面、或图层,用于表示图层、文字或图像的绘制效果,如果不绘制在主图层上,则不会被显示。
pygame.display.set_mode()生成主图层,是一个Surface对象,在主图层上绘制其它图层使用blit()方法
pygame.draw绘制图形后,返回一个矩形Rect类表示形状,
pygame.Rect表达一个矩形区域的类,Pygame利用Rect类来操作图形、图像、文字等信息。对应于当前主图层的某个区域,指定图层绘制的矩形区域。

文字的绘制

系统字体所在位置:

复制微软雅黑到“fonts”文件夹
pygame.freetype类:向屏幕上绘制特定字体的文字,文字不能直接用print(), 而是用像素根据字体点阵图绘制

pygame 包在加载时不会自动导入freetype。必须显式导入此模块才能使用。

import pygame
import pygame.freetype

pygame 1.9.2 中的新功能:freetype

常用的方法

  1. pygame.freetype.Font
    从支持的字体文件创建一个新的Font实例。
    Font(file, size=0, font_index=0, resolution=0, ucs4=False) -> Font
    参数:
    file可以是表示字体文件名的字符串,包含字体的类文件对象,也可以是None;如果为None,则使用默认的Pygame字体。

(可选)可以指定size参数来设置文字的默认大小,这决定了渲染字符的大小。大小也可以显式传递给每个方法调用。由于缓存系统的工作方式,在构造函数上指定默认大小并不意味着在每次函数调用上手动传递大小都会带来性能提升。如果字体是位图并且没有给出大小,则默认大小设置为字体的第一个可用大小。
2. pygame.freetype.Font.render()
将渲染文本作为surface返回
render(text, fgcolor=None, bgcolor=None, style=STYLE_DEFAULT, rotation=0, size=0) -> (Surface, Rect)
返回一个新的Surface,文本以’fgcolor’给出的颜色呈现给它。如果没有给出前景色,则使用默认前景色fgcolor。如果给出bgcolor,Surface将用这种颜色填充。
返回值是一个元组:新Surface和边界矩形给出渲染文本的大小和原点。
如果为文本传递空字符串,则返回的Rect为零宽度和字体高度。

  1. pygame.freetype.Font.render_to()
    将文本渲染到现有surface上
    render_to(surf, dest, text, fgcolor=None, bgcolor=None, style=STYLE_DEFAULT, rotation=0, size=0) -> Rect
    将字符串文本呈现给pygame.Surface对象,位于dest,(x,y)表面坐标对。如果x或y不是整数,则尽可能将其转换为整数。接受前两个项是x和y位置元素的任何序列,包括Rect实例。与render()一样,可以选择fgcolor,style,rotation和size参数。
def word_wrap(surf, text, font, color=(0, 0, 0)):
    font.origin = True
    words = text.split(' ')
    width, height = surf.get_size()
    line_spacing = font.get_sized_height() + 2
    x, y = 0, line_spacing
    space = font.get_rect(' ')
    for word in words:
        bounds = font.get_rect(word)
        if x + bounds.width + bounds.x >= width:
            x, y = 0, y + line_spacing
        if x + bounds.width + bounds.x >= width:
            raise ValueError("word too wide for the surface")
        if y + bounds.height - bounds.y >= height:
            raise ValueError("text to long for the surface")
        font.render_to(surf, (x, y), None, color)
        x += bounds.width + space.width
return x, y

文字版的小球游戏

import pygame, sys
import pygame.freetype

pygame.init()

size = screen_width, screen_height = 640, 480
screen = pygame.display.set_mode(size)
pygame.display.set_caption('文字游戏')

BLACK = pygame.Color('black')
GOLD = (255,251,0)
font1 = pygame.freetype.Font("C://Windows//Fonts//msyh.ttc", 28)
font_surface,font_rect = font1.render("小小工坊", fgcolor=GOLD, size=50)

pos = [screen_width // 2, screen_height // 2]
speed = [1,1]
fps = 60
fclock = pygame.time.Clock()

while True:
	fclock.tick(fps)
	for e in pygame.event.get():
		if e.type == pygame.QUIT:
			sys.exit()
	
	if pos[0] < 0 or pos[0] + font_rect.width > screen_width:
		speed[0] = -speed[0]
	if pos[1] < 0 or pos[1] + font_rect.height > screen_height:
		speed[1] = -speed[1]

	pos[0] = pos[0] + speed[0]
	pos[1] = pos[1] + speed[1]

	screen.fill(BLACK)
	screen.blit(font_surface,(pos[0],pos[1]))

	pygame.display.update()

Python基础学习第十五节 类与继承(类与继承,这一篇就足够了)

Python基础学习之类与继承

1. 面向对象 名词解释

  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。类中定义了类对象所共有的属性和方法。对象是类的实例。
  • 方法:类中定义的函数,被称为:方法。
  • 属性:类中的类变量,我感觉都可以被叫做属性。
  • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • 对象:对象是类的实例。对象包括两个数据成员(类变量和实例变量)和方法
  • 数据成员:类变量或者实例变量, 用于处理类 & 实例对象的数据。
  • 方法重写:父类中已经有了对应的方法,但是在继承时不满足子类的要求,此时可以对父类的方法进行改写,这个过程叫方法的覆盖(override),被称为方法的重写。
  • 局部变量:定义在类中方法内的变量,只作用于当前实例的类。
  • 实例变量:对于每个实例都独有的数据,就是实例变量;在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
  • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
  • 实例化:创建一个类的实例,类的具体对象。

2. 类的详解

Python 中类的创建比较容易,先举一个例子,然后对其进行讲解;

2.1 类的举例:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:Zhang Kai time:2020/10/13

class food:
    
    水果类,用来统计水果的名字和数量;
    
    food_count = 0

    def __init__(self, name, qty):
        self.name = name
        self.qty = qty
        food.food_count += 1

    def print_name(self):
        print(我有%s个%s % (self.qty, self.name))

    def print_food_count(self):
        print(我一共有%s种水果%food.food_count)


apple = food(苹果,10)   # 创建实例对象
# 下面为实例属性的调用
print(apple.name)    # 输出:苹果

# 下面为类属性的调用
print(apple.food_count)   # 输出:1

# 以下两句为:类的方法调用
apple.print_name()    # 输出:我有10个苹果
apple.print_food_count()    # 输出:我一共有1种水果

pear = food(梨,5)   # 创建实例对象
pear.print_name()     # 输出:我有5个梨
pear.print_food_count()     # 输出:我一共有2种水果
apple.print_food_count()     # 输出:我一共有2种水果; 我们可以看到苹果对象的food_count也发生了变化;

说明:

  • food_count = 0;定义了一个类变量,这个变量在所有类的实例之间共享;在上面代码的最后一句apple.print_food_count()我们可以看到水果的种类已经变成了2;
  • def __init__(self, name, qty):;这是一个特殊的方法,被称为类的构造函数或初始化方法,在创建实例的时候,就会调用该方法;这一点非常非常的重要!
  • self: 在定义方法时,我们都首先传入了self 参数,这里的self 代表了所生成的实例本身;虽然在调用时不必传入相应的参数,但是 self 在定义类的方法时是必须传入的,这一点也非常重要!
  • 上面这个简单的例子中,几乎用到了所有类的相关知识,包括:类的定义,类的帮助文档,类的初始化,类的实例,类的属性调用,类的方法调用等;下面对其进行详细介绍;

2.2 创建方法:

使用关键字 class 声明一个类,class 后为类名,再加一个冒号(:)。类的定义语句缩进一个tab 然后书写即可:

class ClassName:
   类的帮助信息   # 类的说明文档
   <语句>   # 类中包含的内容,包括:类成员,方法,数据属性。

2.3 类的帮助文档

与函数一样,在类定义时,使用三个引号即可定义类的帮助文档,我们通过ClassName.__doc__ 的方法就可以调用它,例如上面例子中的:

class food:
    
    水果类,用来统计水果的名字和数量;
     # 定义了帮助文档

print(food.__doc__)    # 输出:水果类,用来统计水果的名字和数量;

2.4 类的初始化

我们可以在类的初始化函数 classname.__init__中对类进行初始化;在创建实例的时候,都会先调用 init 函数;例如:

def __init__(self, name, qty):   # 这里传入的参数,需要再创建实例的时候传入;
	self.name = name   # 把传入的参数赋值给实例的对应属性;
	self.qty = qty   # 把传入的参数赋值给实例的对应属性;
	food.food_count += 1   # 修改类属性的值,这里为:每当新创建一个实例时,就将food_count 加1;

2.5 方法中的self

从上面的初始化函数,我们可以看到,在类中的方法(函数)定义时,必须首先传入一个 self (实际上,叫什么名字都行,只是人们都是用self, 类似于约定俗成); 从上面的例子我们可以看出,self 其实代表的就是即将生成的实例本身;

class Test:
    def prt(self):
        print(self)
        print(self.__class__)
        print(Test)


ob = Test()    
ob.prt()    

输出:

<__main__.Test object at 0x000002730B2C5BA8>
<class __main__.Test>
<class __main__.Test>

从上面的例子我们也可以看出,self 指向的是实例的地址;self.__class__ 指向Test 类;Test 类本身也指向Test 类;

2.6 类的实例创建

Python 中没有类创建的关键字,类的实例化类似函数调用方式。直接调用类,传入参数即可;例如:

apple = food(苹果,10)   # 创建实例对象
pear = food(梨,5)   # 创建实例对象

这样就创建了两个水果实例,是不是非常的简单?

2.7 属性的调用 & 修改

Python 中对于类的属性调用也非常简单,直接用.来调用即可;例如:

# 下面为实例属性的调用
print(apple.name)    # 输出:苹果

# 下面为类属性的调用
print(apple.food_count)   # 输出:1

我们还可以直接修改属性值,例如:

apple.qty=13   # 修改属性值为13
apple.print_name()   # 输出:我有13个苹果

除此之外,python还提供了一些函数,用来访问属性值:

  • getattr(obj, name[, default]) : 访问对象的属性。
  • hasattr(obj,name) : 检查是否存在一个属性。
  • setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
  • delattr(obj, name) : 删除属性。
getattr(apple,qty)   # 得到返回值 13
hasattr(apple,qty)   # qty存在,得到返回值 True
setattr(apple,qty,20)  # 修改数量为 20
delattr(apple,qty)   # 删除属性值

备注:上面的这几个函数,千万注意这里的引号,对象名没有引号,属性名要加引号,切记!

2.8 类的方法创建 & 调用

Python类的方法创建:也比较容易,难的是灵活的应用;定义方法时,和定义普通函数基本一样,仅有的区别去下:

  1. 类的方法定义时,需要首先传入一个self参数;
  2. 类的方法可以调用类的属性和实例的属性;
    def print_name(self):
        print(我有%s个%s % (self.qty, self.name))

    def print_food_count(self):
        print(我一共有%s种水果%food.food_count)

Python 类的调用:直接用实例调用即可,例如上面例子中的代码:

pear.print_name()     # 输出:我有5个梨
pear.print_food_count()     # 输出:我一共有2种水果
apple.print_food_count()     # 输出:我一共有2种水果; 我们可以看到苹果对象的food_count也发生了变化;

2.9 类的内置属性

  • __dict__ : 返回类的属性(包含一个字典,由类的数据属性组成)
  • __doc__ :返回类的文档字符串
  • __name__: 返回类名
  • __module__: 返回类定义所在的模块
  • __bases__ : 返回类的所有父类构成元素(包含了一个由所有父类组成的元组)
print(food.__doc__)         # 输出:水果类,用来统计水果的名字和数量;
print(food.__name__)        # 输出:food
print(food.__module__)      # 输出:__main__
print(food.__bases__)       # 输出:(<class object>,)

# 为了让输出好看一些,引入pprint模块;
import pprint
pprint.pprint(food.__dict__)

food.__dict__ 的输出:

mappingproxy(__dict__: <attribute __dict__ of food objects>,
              __doc__: \\n    水果类,用来统计水果的名字和数量;\\n    ,
              __init__: <function food.__init__ at 0x000001C0A2AA6730>,
              __module__: __main__,
              __weakref__: <attribute __weakref__ of food objects>,
              food_count: 2,
              print_food_count: <function food.print_food_count at 0x000001C0A2AA6840>,
              print_name: <function food.print_name at 0x000001C0A2AA67B8>)

2.10 实例的删除

一个实例的删除,会调用析构函数 __del__; 当对象不再被使用时,__del__方法运行: Python 的析构函数,不需要我们进行调用,程序自己会根据程序的运行自行调用;那么我们为什么要学析构函数呢? 因为,有时我们希望在实例被删除的时候做一些事情,比如本章所使用的例子中,我们希望水果实例被删除的时候,水果种类减1,这是我们就会用到析构函数,举例如下:

class food:
    
    水果类,用来统计水果的名字和数量;
    
    food_count = 0

    def __init__(self, name, qty):
        self.name = name
        self.qty = qty
        food.food_count += 1

    def print_name(self):
        print(我有%s个%s % (self.qty, self.name))

    def print_food_count(self):
        print(我一共有%s种水果%food.food_count)

    def __del__(self):    # 析构函数,应该加在类的创建中
        class_name = self.__class__.__name__
        food.food_count -= 1
        print(self.name, "没有了,我现在有%s种水果" %food.food_count)

# 创建两个实例
apple = food(苹果,10)
pear = food(梨,5)

pear.print_food_count()
# 删除一个实例
del apple
pear.print_food_count()

输出:

我一共有2种水果
苹果 没有了,我现在有1种水果
我一共有1种水果
梨 没有了,我现在有0种水果   # 这一条输出,就是python主动调用析构函数所产生的;

这里我们可以看到,在程序的最后,虽然我们没有删除 梨 这个实例,但是程序运行到最后Python会主动调取析构函数,把所有的实例释放,这就是python厉害的地方;因为别的语言,我们还需要手动调用一次析构函数;而python为我们做了这些工作;

2.11 私有属性 & 私有属性

2.10 中的类的例子,已经比较完整,但是我们发现,我们可以通过修改属性值修改水果的种类数;例如:

food.food_count = 20    # 修改类属性
pear.print_food_count()  # 输出:我一共有20种水果

这样任意修改类属性的值,有时并不是我们想要的结果;例如这里的水果种类,我们只希望在创建实例 & 删除实例的时候,对其进行修改,其他时候我们不可以修改;我们要如何实现呢? 这里就要用到 私有属性 & 私有方法;

2.11.1 私有属性

声明属性时,属性名以两个下划线开头,就定义了私有属性,私有属性不能在类的外部被使用;举例如下:

class food:
    
    水果类,用来统计水果的名字和数量;
    
    __food_count = 0

    def __init__(self, name, qty):
        self.name = name
        self.qty = qty
        food.__food_count += 1

    def print_name(self):
        print(我有%s个%s % (self.qty, self.name))

    def print_food_count(self):
        print(我一共有%s种水果%self.__food_count)

    def __del__(self):    # 析构函数,应该加在类的创建中
        class_name = self.__class__.__name__
        food.__food_count -= 1
        print(self.name, "没有了,我现在有%s种水果" %self.__food_count)

注意这里的几点变化:

  • 声明私有属性时,声明方法为:__food_count = 0,是两个下划线开头;
  • 私有属性的调用时,必须在类的内部!使用self.__food_count 来调用实例的私有属性,使用food.__food_count 来调用类的私有属性;这里有两个重点:1. 只能在类的内部调用;2. 调用时使用self.__food_count调用实例的私有属性 或者food.__food_count来调用类的私有属性;

访问私有属性:Python不允许实例化的类访问私有数据,但有另一种方法:可以使用 object._className__attrName( 对象名._类名__私有属性名 )访问属性,参考以下实例:

class food:
    
    水果类,用来统计水果的名字和数量;
    
    __food_count = 0

    def __init__(self, name, qty):
        self.name = name
        self.qty = qty
        food.__food_count += 1
        self.__print_name()
        self.__print_food_count()

    def __print_name(self):
        print(我有%s个%s % (self.qty, self.name))

    def __print_food_count(self):
        print(我是%s,food类的水果数量为:%s%(self.name,food.__food_count))

    def __del__(self):    # 析构函数,应该加在类的创建中
        class_name = self.__class__.__name__
        food.__food_count -= 1
        print(self.name, "没有了,我现在有%s种水果" %food.__food_count)
        self.__print_food_count()


apple = food(苹果,10)
print(apple._food__food_count)   # 访问了类的私有属性,输出:1

2.11.2 类属性 & 实例属性

上述私有属性定义完成后,我们已经不可以通过外部对其属性进行访问了,保护了数据的安全;但是,这时我们依然可以通过类的方法来修改该属性值,比如我们在类内部定义一个方法add_1来调用私有属性__food_count,就可以增加__food_count的数量,在此之前,我们先来明确一下 类属性 & 实例属性:

class food:
    
    水果类,用来统计水果的名字和数量;
    
    __food_count = 0

    def __init__(self, name, qty):
        self.name = name
        self.qty = qty
        food.__food_count += 1

    def print_name(self):
        print(我有%s个%s % (self.qty, self.name))

    def print_food_count(self):
        print(我是%s,我一共有%s种水果,food类的水果数量为:%s%(self.name,self.__food_count,food.__food_count))

    def __del__(self):    # 析构函数,应该加在类的创建中
        class_name = self.__class__.__name__
        food.__food_count -= 1
        print(self.name, "没有了,我现在有%s种水果" %food.__food_count)

    def add_1(self):
        food.__food_count +=1
        self.print_food_count()


apple = food(苹果,10)
pear = food(梨,5)
apple.add_1()    # 我是苹果,我一共有3种水果,food类的水果数量为:3  
apple.add_1()   # 我是苹果,我一共有4种水果,food类的水果数量为:4
apple.add_1()   # 我是苹果,我一共有5种水果,food类的水果数量为:5
apple.print_food_count()    # 我是苹果,我一共有5种水果,food类的水果数量为:5
pear.print_food_count()     # 我是梨,我一共有5种水果,food类的水果数量为:5
pear.add_1()                 # 我是梨,我一共有6种水果,food类的水果数量为:6

注意:在 initdel , add_1,三个方法中,对私有属性进行修改时,都使用 food.__food_count,因为类属性是所有实例共享的数据。在调用实例属性时,会优先调用实例属性的值,但是在上面的例子中,我们没有定义实例的属性值,这是python会帮我们调用类属性的值; 如果这里全部变更为实例属性 self.__food_count, 则会为每个实例创建实例的私有属性,类的私有属性不会改变,如下:

class food:
    
    水果类,用来统计水果的名字和数量;
    
    __food_count = 0

    def __init__(self, name, qty):
        self.name = name
        self.qty = qty
        self.__food_count += 1

    def print_name(self):
        print(我有%s个%s % (self.qty, self.name))

    def print_food_count(self):
        print(我是%s,我一共有%s种水果,food类的水果数量为:%s%(self.name,self.__food_count,food.__food_count))

    def __del__(self):    # 析构函数,应该加在类的创建中
        class_name = self.__class__.__name__
        self.__food_count -= 1
        print(self.name, "没有了,我现在有%s种水果" %food.__food_count)

    def add_1(self):
        self.__food_count +=1
        self.print_food_count()


apple = food(苹果,10)
pear = food(梨,5)
apple.add_1()    # 我是苹果,我一共有2种水果,food类的水果数量为:0
apple.add_1()   # 我是苹果,我一共有3种水果,food类的水果数量为:0
apple.add_1()   # 我是苹果,我一共有4种水果,food类的水果数量为:0
apple.print_food_count()    # 我是苹果,我一共有4种水果,food类的水果数量为:0
pear.print_food_count()     # 我是梨,我一共有1种水果,food类的水果数量为:0
pear.add_1()                 # 我是梨,我一共有2种水果,food类的水果数量为:0

从上例中我们可以看出,实例的属性self.__food_count 与 类属性 food.__food_count 是完全不一样的;在调用实例属性时,会优先调用实例属性的值self.__food_count,但是在上面的例子中,我们没有定义实例的属性值,这是python会帮我们调用类属性的值food.__food_count

上面这一部分主要说了类属性 & 实例属性;

2.11.3 私有方法

两个下划线开头,声明该方法为私有方法,不能在类的外部调用。在类的内部调用 self.__private_methods;举例如下:

class food:
    
    水果类,用来统计水果的名字和数量;
    
    __food_count = 0

    def __init__(self, name, qty):
        self.name = name
        self.qty = qty
        self.__food_count += 1

    def print_name(self):
        print(我有%s个%s % (self.qty, self.name))

    def print_food_count(self):
        print(我是%s,我一共有%s种水果,food类的水果数量为:%s%(self.name,self.__food_count,food.__food_count))

    def __del__(self):    # 析构函数,应该加在类的创建中
        class_name = self.__class__.__name__
        self.__food_count -= 1
        print(self.name, "没有了,我现在有%s种水果" %food.__food_count)

    def __add_1(self):    # 私有方法定义
        self.__food_count +=1
        self.print_food_count()


apple = food(苹果,10)
pear = food(梨,5)

apple.print_food_count()    # 我是苹果,我一共有4种水果,food类的水果数量为:0
pear.print_food_count()     # 我是梨,我一共有1种水果,food类的水果数量为:0

3. 类的继承

类的继承最大的好处就是代码的重用,通过继承创建的新类称为子类或派生类,被继承的类称为基类或父类。

3.1 继承的特点

1、如果在子类中需要父类的构造方法就需要显式的调用父类的构造方法,或者不重写父类的构造方法。 2、在调用基类的方法时,需要加上基类的类名前缀,且需要带上 self 参数变量。区别在于类中调用普通函数时并不需要带上 self 参数。 3. 调用子类方法时,Python 总是首先查找子类中的方法,如果找不到,它才开始到基类中逐个查找。 4. 如果在子类声明时,继承元组中列了一个以上的类,这就是多重继承。

3.2 继承实例

class Parent:  # 定义父类
    parentAttr = 100

    def __init__(self):
        print("调用父类构造函数")

    def parentMethod(self):
        print(调用父类方法)

    def setAttr(self, attr):
        Parent.parentAttr = attr

    def getAttr(self):
        print("父类属性 :", Parent.parentAttr)


class Child(Parent):  # 定义子类
    def __init__(self):
        print("调用子类构造方法")

    def childMethod(self):
        print(调用子类方法)


c = Child()  # 实例化子类
c.childMethod()  # 调用子类的方法
c.parentMethod()  # 调用父类方法
c.setAttr(200)  # 再次调用父类的方法 - 设置属性值
c.getAttr()  # 再次调用父类的方法 - 获取属性值

3.3 子类的初始化

情况一:子类需要自动调用父类的方法:子类不重写__init__()方法,实例化子类后,会自动调用父类的__init__()的方法。

情况二:子类不需要自动调用父类的方法:子类重写__init__()方法,实例化子类后,将不会自动调用父类的__init__()的方法。

情况三:子类重写__init__()方法又需要调用父类的方法:使用super关键词:super(子类,self).__init__(参数1,参数2,....)

class Child(Parent):
	def __init__(self, name):   
		super(Child, self).__init__(name)

举例:

class Father(object):
    def __init__(self, name):
        self.name = name
        print("name: %s" % (self.name))

    def getName(self):
        return Father  + self.name


class Son(Father):
    def __init__(self, name,age):
        super(Son, self).__init__(name)
        print("hi")
        self.name = name
        self.age = age

    def getName(self):
        return Son: + self.name + \\nage: + self.age


if __name__ == __main__:
    son = Son(runoob,18)
    print(son.getName())

输出:

name: runoob
hi
Son:runoob
age:18

3.4 继承判定函数

python还提供了继承判定的函数:

  • issubclass(sub,sup) 判断一个类sub是另一个类sup的子类或者子孙类,是则返回True;
  • isinstance(obj, Class) 判断 obj是Class类的实例对象或者是一个Class子类的实例对象,是则返回True。
print(issubclass(Parent, Child))    # False
print(issubclass(Child, Parent))    # True
print(isinstance(c, Child))    # True
print(isinstance(c, Parent))   # True

3.5 方法重写

调用子类方法时,Python 总是首先查找子类中的方法,如果找不到,它才开始到基类中逐个查找。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
class Parent:        # 定义父类
   def myMethod(self):
      print 调用父类方法
 
class Child(Parent): # 定义子类
   def myMethod(self):
      print 调用子类方法
 
c = Child()          # 子类实例
c.myMethod()         # 子类调用重写方法

以上是关于Python基础:第020课——Color类与文字绘制的主要内容,如果未能解决你的问题,请参考以下文章

第15课 类与封装的概念

Python基础学习第十五节 类与继承(类与继承,这一篇就足够了)

前端就业课 第一阶段HTML5 零基础到实战伪类与伪元素

JulyEdu-Python基础第 2 课:

Python 类与对象

python 第3课 python 基础语法