面对对象编程

一. 面对对象初步

Python支持面向过程,面向对象,函数式编程等多种编程范式

  • 面向过程(procedure oriented):
    更关注程序的逻辑流程,执行者思维,适合简单,不需要协作的任务
  • 面向对象(Object Oriented):
    更关注软件中对象之间的关系,设计者思维,适合编写大规模程序

1. 面对对象和面对过程对比

  1. 面对对象相当于横向展开,面对过程相当于纵向展开
  2. 复杂问题,必须先横向拆分,再纵向执行两种思路相辅相成

2. 对象的进化

  1. 简单数据
  2. 数组:将同类数据放到一起
  3. 结构体:不同类数据放到一起
  4. 对象:将不同类型和方法放到一起

二. 类的定义

  1. 将对象比作饼干,类就是制造饼干的模具
  2. 通过类定义数据类型的属性(数据)和方法(行为),属性通过变量表示,方法通过函数表示
  3. 对象称为类的实体,对象共享类的行为(类中定义的方法),但会有自己的属性(不共享状态
  4. 类名首字母大写,使用驼峰原则

1. __init__和__new__构造

  1. 名称必须是__init__
  2. 第一个参数必须是self
  3. 用来初始化实例对象的实例属性
  4. 通过类名(参数列表)来调用构造函数,将创建好的对象返回给相应变量
  5. new()无需重新定义,用来创建对象

2. 实例属性

  1. 实例属性是从属于实例对象的属性
  2. 初始化定义:
    def __init__(self,name,score):   #self必须位于第一个参数,若不传入name,score参数,在下面定义,则这一类所有属性都唯一确定
        self.name=name
 
  1. 在本类的其他方法中,也通过self.实例属性名进行访问
  2. 创建实例对象后,通过实例对象访问
  3. 通过实例对象访问时,可以更改已有属性值,也可以添加新属性

3. 实例方法

  1. 定义实例方法时,第一个参数必须为self,self指当前实例对象
  2. 调用时例方法时,不能给self传参,self由解释器自动传参

4. 其他操作

  1. dir(obj)获得对象所有属性,需要print,不只是定义的属性和方法,还有一些基础的属性
  2. obj.dict()获得对象的属性字典,只有属性,没有方法
  3. pass 空语句
  4. isinstance(对象,类型)判断对象是不是指定类型

5. 代码

class Student:    #首字母大写,驼峰原则
    #构造函数
    def __init__(self,name,score):   #self必须位于第一个参数,若不传入name,score参数,在下面定义,则这一类所有属性都唯一确定
        self.name=name
        self.score=score

    def say_score(self):  #self必须位于第一个参数
        print("{0}的分数是:{1}".format(self.name,self.score))

s1=Student("gaogao",18)  #相当于用__new__(一般无需重新定义此方法)创建对象,用__init__(需要在类中定义该方法)初始化
s1.say_score()
s1.name="wang"
s1.age=20
print(s1)   #<__main__.Student object at 0x000001BE7BAFE4C8>
s1.say_score()   #类中定义的属性可以在复制以后更改
print(dir(s1))          #获得对象所有!属性方法(不只有定义的属性和方法(也是一种属性),还有更底层的属性)
print(s1.__dict__)      #对象的属性字典(返回字典类型,里面是定义的属性键对值(不包含方法))
print(isinstance(s1,Student)) #判断对象是不是指定类
s2=Student("li",32)
s2.say_score()
print(s2.__dict__)  #没有age的属性,因为age是s1自定义的,只有方法共享!1



class Student:    #首字母大写,驼峰原则

    def __init__(self):   #self必须位于第一个参数,若不传入name,score参数,在下面定义,则这一类所有属性都唯一确定
        self.name="gaogao"
        self.score=18

    def say_score(self):  #self必须位于第一个参数
        self.sex="man"      #定义在行为里的初始状态是共享的,但是可以修改
        print("{0}的分数是:{1}".format(self.name,self.score))

s1=Student()    #
s1.say_score()
s1.sex="female"
print(s1.sex)

#空语句用pass
class Student:
    pass

三. 类对象/类属性/类方法

1. 类对象

  1. 当解释器执行class语句时,就会创建一个类对象
  2. 类对象可以赋值,类对象的类型是type,实例对象的类型是对应的类名

2. 类属性

  1. 类属性是从属于类对象的属性,也称为类对象,可以被所有实例对象共享
  2. 类属性通过类名来访问
class Student:         #创建类对象
    company="abc"      #类属性
    count=0
    def __init__(self,name,score):    #创建实例对象
        self.name=name
        self.score=score
        Student.count+=1    #类属性通过类名来访问

    def say_score(self):
        print("my company is:",Student.company)
        print("my score is:",self.score)

S1=Student
s2=S1("gao",100)
print(type(S1))    #<class 'type'>类型是“类”,S1是一个类对象
print(type(s2))    #<class '__main__.Student'>Student类型,是一个实例对象
s1.say_score()

3. 类方法

  1. 类方法是从属于类对象的方法
  2. 通过@classmethod来定义,必须位于类方法定义上一行
  3. 第一个参数必须是cls
  4. 调用类方法格式:类名.类方法名(参数列表),不用传cls值
  5. 类方法中访问实例属性和实例方法会导致错误
  6. 实例方法可以调用类方法,用self.函数名调用!!!
class Student:
    company="abc"   #类属性
    @classmethod          #类方法定义上一行要加@classmethod
    def printcompany(cls):     #类方法必须用cls作为第一个参数
        print(cls.company)
    def a(self):                #实例方法可以调用类方法,用self.函数名调用!!!
        self.printcompany()
A=Student()
A.a()

Student.printcompany()   #通过类名加函数名调用类方法

4. 静态方法

  1. 定义与类对象无关的方法,称为静态方法
  2. 需要通过类调用
  3. 通过装饰器@staticmethod调用
class Student:
    company="sbc"
    @staticmethod    #静态方法定义上一行加@staticmethod
    def add(a,b):      #不用cls参数
        print("{0}+{1}:{2}".format(a,b,(a+b)))
        return (a+b)
Student.add(1,2)

5. 析构函数

  1. 实现对象被销毁时所需的操作
  2. Python垃圾回收机制:当对象引用数为0时,垃圾回收器调用__del__方法
  3. 系统会提供__del__方法,不需要自定义
class Person:
    def __del__(self):
        print("销毁对象:{0}".format(self))
P1=Person()
P2=Person()
del P2
print("程序结束")
#P1也被销毁了,因为引用数为0

6. __call__方法和可调用对象


class SalaryAccount:
    def __call__(self,salary):
        print("计算工资")
        yearsalary=salary*12
        daysalary=salary/22.5
        hoursalary=daysalary/8

        return dict(yearsalary=yearsalary,daysalary=daysalary,mothsalary=salary,hoursalary=hoursalary)

S=SalaryAccount()
print(S(30000))

四. Python方法没有重载

  1. 其他语言可以定义多个重名的方法,只要保证方法签名一致即可,方法签名包括三部分:方法名,参数数量,参数类型
  2. Python中,参数没有声明类型,而且参数数量可以有可变参数控制,所以Python没有方法重载
  3. 如果在类体中定义多个重名方法,只有最后一个方法有效

五. 方法的动态性

  1. Python是动态语言,可以在外部通过引用类方法动态的为类添加新的方法,或者动态地修改已有类方法
class Person:
    def work(self):
        print("努力上班")


def play_game(s):   #可以用s也可以用self
    print("{0}玩游戏".format(s))

def work2(s):
    print("好好工作,努力上班")

#用类名增加方法
Person.play=play_game
#用类名修改方法
Person.work=work2
p=Person()
p.play()   #Person.play(p)
p.work()   #Person.work(p)

六. 私有属性和私有方法

  1. Python对于类成员没有严格的访问控制
  2. 通常规定,两个下划线开头的属性是私有的,其他的为公共的
  3. 类内部可以访问私有属性和方法
  4. 类外部不能直接访问私有属性和方法
  5. 类外部通过“_类名__私有属性(方法)名”访问私有属性(方法)
#测试私有属性
class Employee:
    __company="abc"

    def __init__(self,name,age):
        self.name=name
        self.__age=age

e=Employee("gao",18)
print(e.name)
print(e._Employee__age)
print(e._Employee__company)
print(dir(e))
print(e.__dict__)   #{'name': 'gao', '_Employee__age': 18}私有属性在类里面的名字已更改

#私有方法
class Employee:
    __company = "abc"

    def __init__(self, name, age):
        self.name = name
        self.__age = age   #私有属性
    def __work(self):    #私有方法
        print("{0}:{1}岁".format(self.name,self.__age))  #有__,没有_Employee
        print("{0}".format(self.__company))   #实例方法中调用私有类方法,可以用类名调用,也可以用self
        #print("{0}".format(Employee.__company))  # 实例方法中调用私有类方法,可以用类名调用,也可以用self


e = Employee("gao", 18)
print(e.name)
print(e._Employee__age)
print(e._Employee__company)
e._Employee__work()
print(dir(e))
print(e.__dict__)  # {'name': 'gao', '_Employee__age': 18}私有属性在类里面的名字已更改

七. @property装饰器

  1. @property可以将一个方法的调用变成属性调用
  2. @方法名.setter:调用方法并给方法赋值时,执行此方法
#测试property用法
class Employee:

    @property
    def salary(self):
        return 10000

emp1=Employee()
print(emp1.salary)
#print(emp1.salary())   #若没有property,要这样使用



#@property和@setter应用
class Employee:

    def __init__(self,name,salary):
        self.__name=name
        self.__salary=salary

    @property
    def salary(self):
        return self.__salary

    @salary.setter
    def salary(self,salary):
        if 1000 < salary < 50000:
            self.__salary = salary
        else:
            print("录入错误,重新输入")
   '''   
   若不用setter方法,要写判断函数,在调用时更换函数  
    def get_salary(self):
        return self.__salary
    def set_salary(self):
        if 1000<salary<50000:
            self.__salary=salary
        else:
            print("录入错误,重新输入")
     '''
emp1=Employee("gao",60000)
print(emp1.salary)
emp1.salary=70000       #这一步是继续调用的是salary.setter
print(emp1.salary)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值