Python自学13(类进阶)

Python自学13(类进阶)_第1张图片
" 如果你不肯等一等,那我只好更加努力地奔跑,直到能够与你并肩的那一日 "

让你的模子更好用:类进阶

  • 1、类属性和类方法
  • 2、类属性的定义
  • 3、类方法的定义
  • 4、静态方法
  • 5、私有属性,方法
  • 6、特殊方法
    • 6.1、__ init __()
    • 6.2、__ next __()
    • 6.3、__ len __()
    • 6.4、__ str __()
    • 6.5、__ getitem __()
  • 7、继承
  • 8、继承链
  • 9、多继承

1、类属性和类方法

对象属性和对象方法

  1. 之前介绍类的时候,我们学习了对象属性和对象方法
  2. 对象属性和对象方法是绑定在对象这个层次上的
  3. 也就是说需要先创建对象,然后才能使用对象的属性和方法
# 语法
对象 =()

对象.属性
对象.方法()

类属性和类方法(绑定在类这个层面的属性和方法)

  • 使用类属性和类方法,不用创建对象,直接通过类来使用
# 语法.属性
类.方法()

2、类属性的定义

类属性的定义:只要将属性定义在类之中方法之外即可

# 如下属性 1 和属性 2
class 类:
	属性1 = X
    属性2 = Y
    
    def 某方法():
        pass

%1
class Char:
    letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    digits = '0123456789'
# 这里定义了类 Char、有两个类属性
# 这两个类属性分别包含所有大写字母和所有数字
# 可以通过类名来使用这两个类属性、此时无需创建对象
print(Char.letters)
print(Char.digits)
# output:ABCDEFGHIJKLMNOPQRSTUVWXYZ
#        0123456789

%2
# 类所创建出来的对象也能使用类属性
class Char:
    letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    digits = '0123456789'
char = Char()
print(char.letters)
print(char.digits)

3、类方法的定义

类方法的定义:类方法的定义需要借助于装饰器

# 语法
# 定义类方法时、需要在方法的前面加上装饰器 @classmethod
class:
	@classmethod
    def 类方法(cls):
        pass

# 注意与对象方法不同、类方法的第一个参数通常命名为 cls、表示当前这个类本身
# 我们可以通过该参数来引用类属性、或类中其它类方法

# 类方法中可以使用该类的类属性、但不能使用该类的对象属性
# 因为类方法隶属于类、而对象属性隶属于对象
# 使用类方法时可能还没有对象被创建出来

%1
# 在之前 Char 类的基础上、我们加上随机获取任意字符的类方法

import random
# import 语句不仅可用于模块的开头、也可用于模块的任意位置、如函数中

class Char:
    letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    digits = '0123456789'
	
    @classmethod
    def random_letter(cls):
    # 方法 random_letter() 可以从属性 letters 随机获取一个大写字母
        return random.choice(cls.letters)
        # 函数体中的 random.choice() 可从指定序列中随机获取一个元素
	
    @classmethod
    def random_digits(cls):
    # 方法 random_digits() 可以从属性 digits 随机获取一个数字
        return random.choice(cls.digits)
        # 函数体中的 random.choice() 可从指定序列中随机获取一个元素

print( Char.random_digits())
print( Char.random_letter())
# output:6
#        T

4、静态方法

  1. 与类方法有点相似的是静态方法
  2. 静态方法也可直接通过类名来调用,不必先创建对象
  3. 不同在于类方法的第一个参数是类自身(cls),而静态方法没有这样的参数
  4. 如果方法需要和其它类属性或类方法交互,那么可以将其定义成类方法
  5. 如果方法无需和其它类属性或类方法交互,那么可以将其定义成静态方法
# 语法
# 定义静态方法时、需要在方法的前面加上装饰器 @staticmethod
class:
	@staticmethod
    def 静态方法():
        pass

# 之前的类方法
# 我们可以从类属性 letters 和 digits 中随机获取字符
# 如果想要自己来指定字符的范围、并从中获取一个随机字符
# 可以再来定义一个静态方法 random_char()

%1
import random

class Char:
    letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    digits = '0123456789'
	
    @classmethod
    def random_letter(cls):
        return random.choice(cls.letters)
	
    @classmethod
    def random_digits(cls):
        return random.choice(cls.digits)
    
    @staticmethod
    def random_char(string):
        if not isinstance(string, str):
        # 如果 string 不是str 的子类
        	raise TypeError('需要字符串参数')
        
        return random.choice(string)

# 静态方法 random_char 从传入的字符串中随机挑选出一个字符
# 之所以定义成静态方法、是因为它无需与类属性交互
print(Char.random_char('i love xiaohan forever'))
# output:f

5、私有属性,方法

  1. 类属性 letters 和 digits 是为了提供给同一个类中的类方法使用
  2. 但我们可以通过类或对象从类的外部直接访问它们
  3. 可以称为公有方法
  4. 有时我们不想把过多的信息暴露出去
  5. 有没有什么方法来限制属性不被类外部所访问,而是只能在类中使用
  6. 可以称为私有方法
# 语法 
Char.letters
Char.digits

# 语法
# 将属性或方法的名称用 __(两个下划线)开头即可

%1
import random

class Char:
    __letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    __digits = '0123456789'

    @classmethod
    def random_letter(cls):
        return random.choice(cls.__letters)

    @classmethod
    def random_digits(cls):
        return random.choice(cls.__digits)

print(Char.__letters)

# output:AttributeError: type object 'Char' has no attribute '__letters'
# type object 'Char' has no attribute '__letters'(提示类中没有定义这个属性)

# 像这样以 __(两个下划线)开头的属性我们称为私有属性
# 顾名思义、它是类所私有的、不能在类外部使用

# 我们也可以使用 _(一个下划线)前缀来声明某属性或方法是私有的
# 但是这种形式只是一种使用者间的约定、并不在解释器层面作限制

%2
class Char:
    _letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    _digits = '0123456789'

# 上面的 _letters 和 _digits 也可看作私有属性
# 只不过是约定上的私有、通过名称前缀 _(一个下滑线)向使用者告知这是私有的
# 但你如果非要使用、依然可以用

print(Char._letters)
print(Char._letters)
# output:ABCDEFGHIJKLMNOPQRSTUVWXYZ
#        0123456789

6、特殊方法

  1. 类中以 __ 开头并以 __ 结尾的方法是特殊方法,特殊方法有特殊的用途
  2. 它们可以直接调用,也可以通过一些内置函数或操作符来间接调用
  3. 如之前学习过的 __ init __() , __ next __()

6.1、__ init __()

# 语法
__init__() 是非常典型的一个特殊方法
它用于对象的初始化、在实例化类的过程中被自动调用

6.2、__ next __()

# 语法
对迭代器调用 next() 函数便能生成下一个值
这个过程的背后、next() 调用了迭代器的 __next__() 方法

6.3、__ len __()

# 语法
调用 len() 函数时、便能返回一个容器的长度
原因就是容器类中实现了 __len__() 方法、调用 len() 函数时将自动调用容器的 __len__() 方法

6.4、__ str __()

# 语法
在使用 print() 函数时将自动调用类的 __str__() 方法

%1
class A:
    def __str__(self):
        return '这是 A 的对象'
a = A()
print(a)
# output:这是 A 的对象

6.5、__ getitem __()

# 语法
诸如列表、元素、字符串这样的序列
可以通过索引的方式来获取其中的元素、这背后便是 __getitem__() 在起作用

%1
print('abc'[2] )
print('abc'.__getitem__(2))
# output:c
#        c

7、继承

  1. 如果想基于一个现有的类,获取其全部能力
  2. 并以此扩展出一个更强大的类,此时可以使用类的继承
  3. 被继承的类叫作父类(或基类),继承者叫作子类(或派生类)
# 语法
定义时、子类名称的后面加上括号并写入父类
class 父类:
    父类的实现
    
class 子类(父类):
	子类的实现

%1
class A:
    def __init__(self):
        self.apple = 'apple'
    
    def have(self):
        print('I hava an', self.apple)

class B(A):
	def who(self):
		print('I am an object of B')

b = B()
print(b.who())
print(b.apple)
print(b.have())
# output:I am an object of B
#        'apple'
#        I hava an apple

# 可以看到、虽然类 B 中什么都没定义
# 但由于 B 继承自 A、所以它拥有 A 的属性和方法

# 子类 B 中当然也可以定义自己的属性

%2
# 我们在 B 中定义 __init__() 方法
# 并在其中定义了 B 自己的属性 banana
class B(A):
	def __init__(self):
		super().__init__()
		self.banana = 'banana'

b = B()
print(b.banana)
# output:banana

# super().__init__() 这一句代码是什么作用
# 由于我们在子类中定义了 __init__() 方法、这会导致子类无法再获取父类的属性
# 加上这行代码就能在子类初始化的同时初始化父类
# super() 用在类的方法中时、返回父类对象

%3
class A:
    def __init__(self):
        self.apple = 'apple'
    
    def have(self):
        print('I hava an', self.apple)

class B(A):
	def __init__(self):
		super().__init__()
		self.banana = 'banana'
	
	def have(self):
		print('I hava an', self.banana)

b = B()
print(b.have())
# output:I hava an banana

8、继承链

# 语法
子类可以继承父类、同样的、父类也可以继承它自己的父类、如此一层一层继承下去

class A:
	def have(self):
		print('I hava an apple')

class B(A):
	pass

class C(B):
	pass

c = C()
print(c.have())
# output:I hava an apple

# 在这里 A 是继承链的顶端、B 和 C 都是它的子类(孙子类)

# 其实 A 也有继承、它继承自 object
# 任何类的根源都是 object 类
# 如果一个类没有指定所继承的类,那么它默认继承 object

# A 中也可以显式指明其继承于 object
class A(object):
	def have(self):
		print('I hava an apple')

# 如果想要判断一个类是否是另一个类的子类、可以使用内置函数 issubclass() 
issubclass(C, A)
issubclass(B, A)
issubclass(C, B)
# output:True
#         True
#         True

9、多继承

  1. 子类可以同时继承多个父类,这样它便拥有了多份能力
  2. 定义时,子类名称后面加上括号并写入多个父类
# 语法
class A:
    def get_apple(self):
        return 'apple'

class B:
    def get_banana(self):
        return 'banana'

class C(A, B):
    pass

c = C()
print(c.get_apple())
print(c.get_banana())
# output:'apple'
#        'banana'

# 此时 C 便同时拥有了 A 和 B 的能力

你可能感兴趣的:(Python自学,字符串,python,类,编程语言)