在进入机器学习之前,想先大家深入了解一些 python 的进阶操作。接下来的操作会有点抽象,请好好品嚐
回到主题,什麽是物件导向程序设计? 大家或多或少打开别人写的程序码会看到 class (类别),写成这个样式有什麽优点吗? 以下列举三项:
我们接着会将想实作的概念抽象化,方便大家使用。python 的套件基本上都是一个个物件哦!前面介绍的 pandas、matplotlib、seaborn,原始码都是写成物件导向。
OS:若想要往更高阶的 python 技巧,物件导向可是非常重要一定要会的!
定义一个物件有的属性(attribute)和方法(method),举例定义一个动物,他的名称和颜色是属性,而动作是方法。Animal 是一个类别名称,在类别内定义的变数称为属性、而定义的函式为方法。提醒一下这边开始会看到很多 self 的关键字,这个代表自己的意思(想像成英文的代名词),楼下这个 self 就是 animal。
你会在每个 method 最前面的第一个参数都必定写 self
class Animal:
# 定义属性 (Attribut)
name = '小黑'
color = '黑色'
# 定义方法 (Method)
def walk(self):
return '走路'
若想操作类别的属性和方法,必须先宣告实体化该物件
# 先实体化後指定给该变数,而该变数则为物件
a = Animal()
print("Type :", type(a))
print("Attribute 1 :", a.name)
print("Attribute 2 :", a.color)
print("Method :", a.walk())
>>> Type : <class '__main__.Animal'>
Attribute 1 : 小黑
Attribute 2 : 黑色
Method : 走路
在建立物件的同时,程序会自动执行的方法称为建构元,又称为初始化。
这个通常是我们写物件的「起手式」。
class Animal:
def __init__(self, name, color):
print("Initialize")
self.name = name
self.color = color
def call(self):
print(f"The color of my {self.name} is {self.color}")
# 实体化的时候就会进行初始化的动作
a = Animal('小黑', '黑色')
>>> Initialize
a.call()
>>> The color of my 小黑 is 黑色
print(a.name)
>>> 小黑
class Circle:
def __init__(self):
self.radius = 10
radius = 5
c = Circle()
c.radius
>>> 10
class Car:
wheel_num = 4
def __init__(self, brand):
self.brand = brand
def drive(self):
print(f"It has {Car.wheel_num} wheels.")
print(f"I can drive my {self.brand} car.")
Car.wheel_num
>>> 4
c = Car('Toyota')
c.drive()
>>> It has 4 wheels.
I can drive my Toyota car.
class Tricycle:
wheel_num = 3
def __init__(self, brand):
self.brand = brand
def drive(self):
print(f"It has {Car.wheel_num} wheels.")
print(f"I can drive my {self.brand} car.")
c = Tricycle('Toyota')
c.drive()
>>> It has 4 wheels.
I can drive my Toyota car.
class Car:
wheel_num = 4
def __init__(self, brand):
self.brand = brand
def drive(self):
print(f"It has {self.__class__.wheel_num} wheels.")
print(f"I can drive my {self.brand} car.")
c = Car('Toyota')
c.drive()
>>> It has 4 wheels.
I can drive my Toyota car.
class Circle:
pi = 3.14
def __init__(self, radius):
self.radius = radius
def calculate_area(self):
self.area = (radius**2) * self.__class__.pi
倘若我去实例化去修改它,c2.pi 、Circle.pi 没有仍然被修改到
c1 = Circle(1)
c2 = Circle(2)
c1.pi = 3.14159
print("c1.pi:", c1.pi)
print("c2.pi:", c2.pi)
print("Circle.pi:", Circle.pi)
>>> c1.pi: 3.14159
c2.pi: 3.14
Circle.pi: 3.14
刚刚介绍的类别,其类别内的属性与方法都可以让外部引用,称为公有属性或公有方法
如果我们想要隐密一点,创建私有的属性和方法,则称为「封装」(Encapsulation)。
class Bank:
def __init__(self, name):
self.name = name
self.balance = 0
def save_money(self, money):
self.balance += money
def withdraw_money(self, money):
self.balance -= money
def show_money(self):
print(f"{self.name} balance is NT${self.balance}.")
b = Bank("David")
b.save_money(1500)
b.show_money()
>>> David balance is NT$1500.
b.balance = 100000000
b.show_money()
>>> David balance is NT$100000000.
为了避免有心人士窜改数据,我们要求外部不得直接更改数据
class Bank:
def __init__(self, name):
self.name = name
self.__balance = 0
def save_money(self, money):
self.__balance += money
def withdraw_money(self, money):
self.__balance -= money
def show_money(self):
print(f"{self.name} balance is NT${self.__balance}.")
b = Bank("David")
b.balance = 100000000
b.show_money()
>>> David balance is NT$0.
私有属性其实只是换上不同名称(python将该属性的名称做调整),告诉其他开发者说这个不要串改或使用
b._Bank__balance = 10000000
b.show_money()
>>> David balance is NT$10000000.
除了双底线开头的私有变数之外,单底线开头(不以底线结尾)的变数也算是私有变数
这是属於约定俗成的写法,依旧可以存取
虽然可以存取,但别人设定写私有就不要随意取用
我们想定义动物的物件,目前我家只养了两只动物就要写两个物件
但一旦到了动物园,有很多动物,每个动物叫声(方法)都不太一样,那不就要写很多次吗?
我们是不是可以用抽象的方式来定义呢?
class Dog:
def __init__(self, name):
self.name = name
def sleep(self):
print("I like sleeping.")
def bark(self):
print("bark bark bark")
class Cat:
def __init__(self, name):
self.name = name
def sleep(self):
print("I like sleeping.")
def meow(self):
print("meow meow meow")
上述的做法没有不对,但是不够好
改良一下把他们抽象化一点,把一样的东西抽出来,加上继承吧!
class Animals:
def __init__(self, name):
self.name = name
print(f"My name is {self.name}")
def talk(self):
pass
class Dog(Animals):
def __init__(self, dog_name):
super().__init__(dog_name)
def talk(self):
print("bark bark bark")
class Cat(Animals):
def __init__(self, cat_name):
super().__init__(cat_name)
def talk(self):
print("meow meow meow")
实际呼叫看看吧!
d = Dog('小黑')
d.talk()
>>> My name is 小黑
bark bark bark
c = Cat('小皮')
c.talk()
>>> My name is 小皮
meow meow meow
在物件导向的程序设计,类别是可以被继承的哦!
被继承的类别为父类别;继承的类别为子类别
类别定义外的私有属性或方法,子类别无法读取,使用上请注意!
class Animals:
def __init__(self, name):
self.name = name
print(f"My name is {self.name}")
def talk(self):
pass
def author(self):
self.__title = 'Erik'
def author_title(self):
return self.__title
class Dog(Animals):
def __init__(self, dog_name):
super().__init__(dog_name)
def talk(self):
print("bark bark bark")
class Cat(Animals):
def __init__(self, cat_name):
super().__init__(cat_name)
def talk(self):
print("meow meow meow")
d = Dog('小黑')
>>> My name is 小黑
# 无法直接取得!
d.author()
d.__title()
>>> AttributeError: 'Dog' object has no attribute '__title'
# 我有给你方法,所以请透过我!
d.author_title()
>>> 'Erik'
在昨天我们简单介绍了框架是如何产生配对後,今天我们要来部署 Open-Match 所需要的环境与核心...
观赏鱼辨识系统说明-Day 01 在接下来的30天会制作一个完整的系统包含前端-手机/网页,後端-N...
接续昨天提到的,我们今天将会实际跑一次指令,如果看到这里的你还在犹豫的话,别犹豫了,跟我一起开始吧!...
大家好,我是17King~ d(`・∀・)b 好久不见,因为最近比较多事情! 但!我没有忘记要po(...
该文章同步发布於:我的部落格 在我一开始学习写 Rails 测试时,会有很常见的问题,就是到底什麽...