没接触过任何语言之前,我了解到的类,好像只有 Java 和 C 里面才有,也觉得特别高大上,就像我第一次接触函数一样,函数可能好理解一点,类就是正儿八经的面对对象编程了。

在书上看了一下类,没接触过的我,确实有点难理解。

通过举例和实际操作来理解一下吧,我也刚接触,无法用概念性的方式表达。

因为是面向对象编程,所以使用类可以进行创建对象,也叫 实例化,要实现这样的功能,就需要类具备一些统一的特点,或者说在定义类对象都有通用行为,也就是有相同的特点,比如,狗,都会跑、跳、蹲,就可以创建一个狗的类,用来实例化,每一只狗,让狗来完成类中定义的 方法,可以是各种不同的狗,因为狗都会跑、跳、蹲,所以都适用于此方法。

函数 的优点相同,让相似的代码可以高效,也可以放在模块中进行调用

创建类

就以上面的例子来创建一个 Dog 类,来表达狗

根据 Dog 类创建的每个实例(对象)都将存储名字和年龄。然后给每条狗一个蹲、打滚、跳的能力

class Dog():
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def sit(self):
        print(self.name.title() + " is now sitting~")

    def roll_over(self):
        print(self.name.title() + " rolled over!")

    def jump(self):
        print(self.name.title() + " is jumped ~")

class Xxx(): 是定义类的格式,在 Python 中,首字母大写的名称指的是类,这个类定义中的括号是空的,因为要从空白创建这个类。

方法 __init__():类中函数就叫方法,每个空白类都有这样一个方法,__init__ 是一个特殊的方法,每当根据这个类创建新实例时,Python都会自动运行__init__ 方法,在这个方法的名称中,开头和末尾都有两个下划线,这是一种约定,是为了避免 Python 默认方法与普通方法发生名称冲突。

以上 __init__ 中包含了三个形参:self、name和age。形参 self 必不可少,还必须在其他形参的前面,Python在调用 __init__ 时,将自动传入实参 self。每个与类相关联的方法调用都自动传递实参 self,是一个指向实例本身的引用,让实例能够访问类中的属性和方法。所以手动调用传参时,也不需要给 self 传参。直接给 name 和 age 按顺序提供值即可。

self.name = name:以 self 为前缀的变量都可以让类中的所有方法使用,这种形式的变量也叫属性。

剩余的 def 定义的方法就是实例化时可以做的动作,如果这是一个做机器狗的代码,就可以将方法替换为机器狗可以做的动作。

创建类实例

my_dog = Dog('包子', '3')

print("My dog's name is " + my_dog.name.title() + ".")
print(my_dog.name.title() + " is " + my_dog.age + " years old.")

以上代码中使用 Dog 类定义 my_dog 变量,并分别传参给了类中 __init__ 函数的 name 和 age 形参,my_dog 就可以成为是 Dog 类的实例,print 语句就是使用该实例化后的参数,所以 my_dog.name 的值为“包子”,my_dog.age 的值为“3”。

调用类方法

根据创建好的实例,调用 Dog 类中的其他方法

my_dog.sit()
my_dog.roll_over()
my_dog.jump()

直接运行以上代码将会得到在类中定义好的输出。可以自行想一个场景,自己做一个联系来巩固类的基础用法。

这里我创建一个简单的示例,同时也方便后续的操作。

class User():
    def __init__(self, first_name, last_name, age):
        self.first_name = first_name
        self.last_name = last_name
        self.age = age

    def describe_user(self):
        print("My name is " + self.first_name + " " + self.last_name + ",I am " + str(self.age) + " years old!")

    def greet_user(self):
        print("Hi, " + self.first_name + self.last_name + "!")

me_user = User('Chai', 'Yanjiang', '26')
me_user.describe_user()
me_user.greet_user()

只要弄懂了类的使用方法,看懂这段毫不费力。

给属性指定默认值

这里的属性指的就是 __init__ 中进行初始化的各类变量值。类中的每个属性都必须有初始值,哪怕为0或者为空,比如宝宝一直未出生之前,年龄一直为0,类中可以这样写。

class User():
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name
        self.age = 0

    def describe_user(self):
        print("My name is " + self.first_name + " " + self.last_name + ",I am " + str(self.age) + " years old!")

    def greet_user(self):
        print("Hi, " + self.first_name + self.last_name + "!")

me_user = User('Chai', 'Yanjiang')
me_user.describe_user()
me_user.greet_user()

这种情况可以让 age 属性一直为0,不需要传参。

但是宝宝出生后,年龄是会有变化的,所以修改的途径还得有。

me_user = User('Chai', 'Yanjiang')
me_user.age = 26
me_user.describe_user()

通过方法传递参数的变化

class User():
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name
        self.age = 0

    def describe_user(self):
        print("My name is " + self.first_name + " " + self.last_name + ",I am " + str(self.age) + " years old!")

    def greet_user(self):
        print("Hi, " + self.first_name + self.last_name + "!")

    def age_change(self, change):
        self.age = change

me_user = User('Chai', 'Yanjiang')
me_user.age_change(23)
me_user.describe_user()

为了防止使用者会将年龄回调,这里可以加个判断。

class User():
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name
        self.age = 0

    def describe_user(self):
        print("My name is " + self.first_name + " " + self.last_name + ",I am " + str(self.age) + " years old!")

    def greet_user(self):
        print("Hi, " + self.first_name + self.last_name + "!")

    def age_change(self, change):
        if change > self.age:
            self.age = change
        else:
            print('Your input is not reasonable')

me_user = User('Chai', 'Yanjiang')
me_user.age_change(23)
me_user.describe_user()

再多一种操作,当每年递增的时候,每年都要算多少岁,直接在原来的基础上加就好了。

class User():
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name
        self.age = 0

    def describe_user(self):
        print("My name is " + self.first_name + " " + self.last_name + ",I am " + str(self.age) + " years old!")

    def greet_user(self):
        print("Hi, " + self.first_name + self.last_name + "!")

    def age_change(self, change):
        if change >= self.age:
            self.age = change
        else:
            print('Your input is not reasonable')

    def increasing_age(self, increasing):
        self.age += increasing

me_user = User('Chai', 'Yanjiang')
me_user.age_change(23)
me_user.describe_user()
me_user.increasing_age(2)
me_user.describe_user()

### 输出内容 ###
My name is Chai Yanjiang,I am 23 years old!
My name is Chai Yanjiang,I am 25 years old!

举的例子可能不太恰当,但是就是这么个事儿。

下面为贴2个例子

示例1:

class User():
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name
        self.login_attempts = 0

    def describe_user(self):
        print("My name is " + self.first_name + " " + self.last_name + ".")

    def greet_user(self):
        print("Hi, " + self.first_name + self.last_name + "!")

    def increment_login_attempts(self):
        self.login_attempts += 1
        print("User " + self.first_name + " " + self.last_name + " attempts to log in " + str(self.login_attempts) + " times!!!")

    def reset_login_attempts(self):
        self.login_attempts = 0
        print("User " + self.first_name + " " + self.last_name + " logins have been reset to " + str(self.login_attempts) + ".")


login_user = User('Chai', 'Yanjiang')
login_user.increment_login_attempts()
login_user.increment_login_attempts()
login_user.increment_login_attempts()
login_user.increment_login_attempts()
login_user.reset_login_attempts()

示例2:

class Restaurant():
    def __init__(self, restaurant_name, cuisine_type):
        self.restaurant_name = restaurant_name
        self.cuisine_type = cuisine_type
        self.number_served = 0

    def desscribe_restaurant(self):
        print("This is a " + self.cuisine_type + ".")
        print("It's called " + self.restaurant_name + ".")

    def open_restaurant(self):
        print("Restaurant is open")
        print("There are " + str(self.number_served) + " people in the restaurant now.")

    def set_num_served(self, set_num):
        if set_num >= self.number_served:
            self.number_served = set_num
            print("There are " + str(self.number_served) + " people eating at " + self.restaurant_name + " " + self.cuisine_type + ".")

    def increment_num_served(self, inc_num):
        self.number_served += inc_num
        print("There are " + str(inc_num) + " new people in the restaurant.")
        print("There are " + str(self.number_served) + " people in the restaurant now.")

restaurant = Restaurant('FeiYi', 'Farmhouse')
restaurant.desscribe_restaurant()
restaurant.open_restaurant()
restaurant.set_num_served(3)
restaurant.increment_num_served(5)

继承

类的继承是指一个类继承另一个类中的所有属性和方法。原有的类称为父类,新类称为子类。子类可以继承父类的所有属性和方法,也可以定义属于自己的属性和方法。

子类通过 __init__ 来继承父类的属性和方法。还以上面 User 例子来使用。

class User():
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def describe_user(self):
        print("My name is " + self.first_name + " " + self.last_name + "!")

    def greet_user(self):
        print("Hi, " + self.first_name + self.last_name + "!")

创建子类时,父类必须在同一代码文件中,且位于子类前面。

class New_User(User):     # 括号内指定父类的名字
    def __init__(self, first_name, last_name):     # __init__ 和父类一致
        super().__init__(first_name, last_name)    # 这行代码让python调用父类User的__init__方法。

super() 函数用来串联父类和子类。让 New_User 包含父类的所有属性,父类也叫超类(superclass),super() 函数也是这么来的。

子类的使用方法和父类一致。

hello = New_User("chai", "yanjiang")   # 定义变量,使用子类并按照父类传参
hello.describe_user()                  # 使用变量,调用父类方法执行

python2.7 在继承父类时,需要给 super() 传参,具体查一下吧,这里就以 python3 为例了。

定义子类私有属性

继承父类后,子类也可拥有属于自己的属性和方法。

class New_User(User):
    def __init__(self, first_name, last_name):
        super().__init__(first_name, last_name)
        self.age = 0   # 新增一个属性,默认值为0

    def new_age(self):     # 新增一个方法,输出人物年龄
        print(self.first_name.title() + " " + self.last_name + "'s age is " + str(self.age))

使用子类中的新增属性和方法

hello = New_User("chai", "yanjiang")
hello.age = 26   # 修改子类属性值
hello.new_age()  # 调用子类方法

重写父类方法

重写其实也可以理解为覆盖,在子类中命名一个和父类中某一方法同名的即可。在调用子类中的该方法时,python 会忽略父类中的同名方法。

使用场景是,如果父类中的方法,在子类的使用过程中不适用的情况。

这个很简单,就不举例了。

将实例用作属性

在定义某一个类时,添加的方法和属性会越来越多,单个类的大小长度也随之变大,可以将大型类拆分成多个小类进行协同使用。

还以上面的代码为例

# 这是最初始的类,用来传入名字,进行介绍和打招呼
class User():
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def describe_user(self):
        print("My name is " + self.first_name + " " + self.last_name + "!")

    def greet_user(self):
        print("Hi, " + self.first_name + self.last_name + "!")

# 想要给这个方法增加一个年龄的属性,假设以上类已经足够大了,重新创建一个类来表示年龄
class User_Age():
    def __init__(self, user_age=0):
        self.user_age = user_age

    def age_info(self):
        print("This is people's age is " + str(self.user_age))

# 上述两个类并无实际关系,然后使用继承和实力属性化的方式结合起来
class New_User(User):
    def __init__(self, first_name, last_name):
        super().__init__(first_name, last_name)    # 继承User父类的属性和方法
        self.age = User_Age()   # 这里直接调用了 User_Age() 类,在使用时,self.age 就已经是一个类了

通过子类使用以上三个类

# 定义变量的值为子类并传参
hello = New_User("chai", "yanjiang")
# 使用变量通过子类调用父类方法
hello.describe_user()
# 使用变量通过子类中定义的属性age,调用表示年龄的类
hello.age.age_info()   # hello.age 中的age 就是 New_Uesr 中 init 方法中的 self.age,即 User_Age()

我尝试了好几次,怎么改这个age的参数,最后改了 User_Age 类为如下:

class User_Age():
    def __init__(self, user_age=0):
        self.user_age = user_age

    def age_info(self, age):
        self.user_age = age
        print("This is people's age is " + str(self.user_age))

使用时传入年龄参数 hello.age.age_info(26)

导入类

随着在使用类的过程中,功能越来越多多,代码越来越多,程序文件会变得越来越长,为了让文件更简洁,Python 允许将类存储在模块中,然后在其他程序文件中导入所需的模块。

使用下面代码作为一个类模块存储,也就是将这个类单独放在一个文件中。

# name.py
class User():
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def describe_user(self):
        print("My name is " + self.first_name + " " + self.last_name + "!")

    def greet_user(self):
        print("Hi, " + self.first_name + self.last_name + "!")

在同级目录创建另一个程序文件来导入上面的类模块

# my_name.py
from name import User

my_name = User("Fei", "Yi")
my_name.describe_user()

from name 表示来自 name.pyimport User 表示导入 name.py 中的 User 类,这里可以看出,也可以导入多个类,也就是 name.py 中可以写入多个类供其他程序文件使用。

一次性导入同一个模块的多个类可以表示为 from name import class1, class2,当然如果存储的模块中有大量类,也可以直接全部导入,使用 import name

import name
# 此处调用类需要使用name.class_name
my_name = name.User("Fei", "Yi")
my_name.describe_user()

评论




正在载入...
PoweredHexo
HostedAliyun
DNSAliyun
ThemeVolantis
UV
PV
BY-NC-SA 4.0