python之面向对象基础一

假设我们要处理学生的成绩表,为了表示一个学生的成绩:
面向过程的方法:用一个dict表示,在进行函数调用

std1 = { 'name': 'Michael', 'score': 98 }
std2 = { 'name': 'Bob', 'score': 81 }
#而处理学生成绩可以通过函数实现,比如打印学生的成绩:
def print_score(std):
    print('%s: %s' % (std['name'], std['score']))
print_score(std2)
print_score(std1)
Bob: 81
Michael: 98

面向对象的方法:创建出这个学生对应的对象,给对象发一个print_score消息,让对象自己把自己的数据打印出来。

class Student(object):
    # 定义初始化方法,创建实例对象自动调用,对属性赋值
    def __init__(self, name, score):
        self.name = name
        self.score = score
    def print_score(self):
        print('%s: %s' % (self.name, self.score))
hongenjie = Student('洪恩节',100)
lisa = Student('Lisa Simpson', 87)
hongenjie.print_score()
lisa.print_score()
洪恩节: 100
Lisa Simpson: 87

面向对象和面向程序的区别:

如果采用面向对象的程序设计思想,我们首选思考的不是程序的执行流程,
而是Student这种数据类型应该被视为一个对象,这个对象拥有name和score这两个属性。

如果要打印一个学生的成绩,首先必须创建出这个学生对应的对象,
给对象发一个print_score消息,让对象自己把自己的数据打印出来,给对象发消息实际上就是调用对象对应的关联函数,我们称之为对象的方法

面向对象的设计思想是抽象出Class,根据类创建实例,面向对象的抽象程度又比函数要高,因为一个Class既包含数据,又包含操作数据的方法

创建对象和定义类:

经典类:class Cat:

# 定义一个猫类
class Cat:
    # 定义猫的属性(color,legs)
    color = '黄色'
    legs = 4
    # 定义猫的方法(eat,sleep)
    def eat(self):
        print('猫吃鱼')
    def sleep(self):
        print('猫睡觉')
my_cat=Cat()#创建实例my_cat
my_cat.eat()#访问方法
my_cat.sleep()#访问方法
print(Cat.color)#访问属性
print(Cat.legs)#访问属性
猫吃鱼
猫睡觉
黄色
4

新式类:class Car(object):

# 定义一个车类
class Car(object):
    # 属性:颜色,四个轮子
    color = '白色'
    wheel = 4
    # 行为:跑,鸣笛
    def move(self):
        print('车子在移动')
    def whistle(self):
        print('车子在鸣笛')
my_car=Car()
my_car.move()
my_car.whistle()
print(Car.color)
print(Car.wheel)
车子在移动
车子在鸣笛
白色
4

实例的作用:

当创建实例对象的时候,对象自动拥有方法,对象就可以直接调用方法(属性也一样)。

对象属性的添加和获取:

属性的添加语法格式:对象名.属性名 = 新的值
属性的获取语法格式:print(对象名.属性名)
对象调用的方法语法格式:对象名.方法名()

#定义一个关于person的类
class Person(object):#属性:身高,体重,年龄#行为:吃饭 睡觉 喝水
	#定义普通的方法
    def eat(self):
        print('人都要吃饭')
    def sleep(self):
        print('人都要休息')
    def drink(self):
        print('水是生命之源')
#通过Person创建一个实例对象p
p = Person()
#直接添加属性
p.name = '张三'
p.age = 20
p.height=180
p.weight=60
#获取属性
print(p.name)
print(p.age)
print(p.height)
print(p.weight)
#对象调用方法
p.eat()
p.sleep()
p.drink()
张三
20
180
60
人都要吃饭
人都要休息
水是生命之源

不仅如此,我们还可以创建新的对象p2,它可以和p有不同的属性,但他们含有相同的方法。

#通过Person创建一个对象p2
p2 = Person()
#直接添加属性
p2.name = '李四'
p2.age = 30
p2.sex = '男'
#获取属性
print(p2.name,p2.age,p2.sex)
#对象调用方法
p2.eat()
p2.sleep()
p2.drink()
李四 30 男
人都要吃饭
人都要休息
水是生命之源

类中的函数称为方法,我们在python前面的基础学习中,学到的任何函数都适用于方法,唯一的区别在于调用方法的方式不同。

init()方法的使用:

init(self,属性1,属性2)是一个特殊的方法,每当我们所创建的类产生新的示例的时候,python都会自动运行它,在这个运行方法的名称中,开头和末尾均有两个下划线,这是避免与普通方法名称产生矛盾,因此必须确保__init__(self,属性1,属性2)的两边都有两个下划线,否则当你使用类来创建示例时,将不会自动调用这个方法,进而引发难以发现的错误。

举例:

#定义一个汽车类
class Car(object):
    def __init__(self,color,wheelNum):
        self.color = color
        self.wheelNum = wheelNum
    # 定义一个普通方法
    def move(self):
        print('车子在移动')
    # 定义一个普通方法
    def whistle(self):
        print('车子在鸣笛')
#创建一个对象bmw
bmw = Car('红色',4)
#调用类里面普通方法
bmw.move()
bmw.whistle()
print(bmw.color)
print(bmw.wheelNum)

细心的小伙伴可能都发现了为什么__init_()属性里面包含了self.
为何必须在方法定义中包含形参self呢?
因为python调用这个方法创建示例时,将自动传入实参self,每个与示例相关联的方法调用都自动传递实参self,它是一个指向示例本身的引用,让示例能够访问类中的属性和方法。
属性我们可以在编写__init__()的时候将属性的值指定,也可以是通过实参来传递属性的值。

指定属性的值:

 def __init__(self,color,wheelNum):
        self.color = '黑色'
        self.wheelNum = 4

不指定属性的值:

 def __init__(self,color,wheelNum):
        self.color = color
        self.wheelNum = wheelNum

那么这两种有什么区别?
区别在于如果指定了属性的值,那么在调用属性的时候,即使实参传递了和指定值不相同的,输出结果依然为指定值。
举例:

def __init__(self,color,wheelNum):
    self.color = '黑色'
    self.wheelNum = 4
bmw = Car('红色',4)
print(bmw.color)
print(bmw.wheelNum)
黑色
4

难道属性的值就不能被改变吗?当然不是
下面我们对上面例子中的属性进行修改:

bmw.color="yellow"
bmw.wheelNum=10

直接修改 对象名.属性名 = 新值
完整代码:

class Car(object):
    def __init__(self,color,wheelNum):
        self.color = '黑色'
        self.wheelNum = 4
    def move(self):
        print('车子在移动')
    def whistle(self):
        print('车子在鸣笛')
bmw = Car('红色',4)
bmw.move()
bmw.whistle()
bmw.color="yellow"
bmw.wheelNum=10
print(bmw.color)
print(bmw.wheelNum)

这次的颜色和车轮数很好的被修改了

车子在移动
车子在鸣笛
yellow
10

当实例化类得到具体对象的时候,会自动调用__init__()方法,对类的属性进行初始化赋值,创建对象的时候,自动拥有类里面属性

__del__析构方法:

import time
#定义一个动物类
class Animal(object):
    #定义初始化方法  创建对象时候自动调用
    def __init__(self,name):
        print('__init__方法被调用')
        self.name = name
    #定义普通方法
    def walk(self):
        print('动物会跑')
    #定义一个析构方法  删除对象的时候自动调用
    def __del__(self):
        print('__del__方法被调用')
        print('%s对象被干掉'%(self.name))
#创建一个dog对象
dog = Animal('哈皮狗')
dog.walk()
__init__方法被调用
动物会跑
__del__方法被调用
哈皮狗对象被干掉

通过输出结果我们发现,为什么__del__()也被调用了呢?
原因是:析构函数__del__(),使用del删除实例时才触发,否则等到文件执行完毕进行回收时才触发。
修改之后:

import time
# 定义一个动物类
class Animal(object):
    #定义初始化方法  创建对象时候自动调用
    def __init__(self,name):
        print('__init__方法被调用')
        self.name = name
    #定义普通方法
    def walk(self):
        print('动物会跑')
    #定义一个析构方法  删除对象的时候自动调用
    def __del__(self):
        print('__del__方法被调用')
        print('%s对象被干掉'%(self.name))
#创建一个dog对象
dog = Animal('哈皮狗')
dog.walk()
# 手动销毁对象,再测试对象调用类中方法报错
del dog
dog.walk()

python之面向对象基础一_第1张图片此时编译器告诉我们dog没有被定义,事实上是因为使用del将其删除了

上面代码中,dog只被引用了一次,因此使用一次del,该对象就被真正的删除了,那么如果是下面这种情况呢?
cat被引用了3次,如果我们去用和面一样的方法,会成功实现对象的删除吗?

cat=Animal("波斯猫")
cat2=cat
cat3=cat

删除cat,去调用cat2和cat3

class Animal(object):
    def __init__(self,name):
        print('__init__方法被调用')
        self.name = name
    def walk(self):
        print('动物会跑')
    def __del__(self):
        print('__del__方法被调用')
        print('%s对象被干掉'%(self.name))
cat=Animal("波斯猫")
cat2=cat
cat3=cat
del cat
cat3.walk()
cat2.walk()
__init__方法被调用
动物会跑
动物会跑
__del__方法被调用
波斯猫对象被干掉

cat2和cat3成功被调用了,难道是对象没被删除?下面我们调用一下cat.

class Animal(object):
    def __init__(self,name):
        print('__init__方法被调用')
        self.name = name
    def walk(self):
        print('动物会跑')
    def __del__(self):
        print('__del__方法被调用')
        print('%s对象被干掉'%(self.name))
cat=Animal("波斯猫")
cat2=cat
cat3=cat
del cat
cat.walk()
Traceback (most recent call last):
  File "C:/Users/Lenovo/PycharmProjects/pythonProject4/main.py", line 295, in <module>
    cat.walk()
NameError: name 'cat' is not defined
__init__方法被调用
__del__方法被调用
波斯猫对象被干掉

通过结果我们可得出如下结论:
在本例中,cat被删除,但不影响cat2/cat3的调用,其他情况亦是如此。

变量保存了对象的引用,对象的引用计数加1,使用__del__()删除对象的时候,对象的引用计数-1,对象被删除,如果对象的引用计数不是1,每删除一次对象的引用计数减1,直到引用计数为0时候,该对象才被真正的删除

你可能感兴趣的:(python,python,开发语言,机器学习,重构)