python-面向对象

2021/10/7 11:12:36

本文主要是介绍python-面向对象,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

①思想:

  • 面向对象 vs 面向过程
  • 以模块化思想解决工程问题
  • 由面向过程转换面向对象
  • 面向对象的例子:
    • 面向对象就好比,你去饭店吃饭,你只需说明想吃什么就可以了,没必要去了解这个菜是怎么做的;反侧就是面向过程。
  • 常用名词
    • oo:面向对象
    • ooa:分析
    • ood:设计
    • oop:编程
    • ooi:实现
    • ooa-> ood-> ooi
  • 类 vs 对象
    • 类:抽象,叙述的是一个集合,侧重于共性
    • 对象:具象,描述的是个体
    • 类的内容:
      • 动作,函数
      • 属性,变量

②定义类:

  • 需用class关键字
  • 类命名
    • 遵循“大驼峰”
    • 首字母大写
#定义一个类
class Student():
#定义空类时,可用pass当做占位符
    pass

#定义类中的函数一般需用self站位(self可替换),例如:   
class StudentAll():
    name = 'cjl'
    age = 18
    language = 'python'
    def hello(self):
        print("你好!")
        
student = StudentAll()
student.hello()
print(student.name, student.age, student.language)

#执行结果:
'''
你好!
cjl 18 python
'''

③self:

  • self在对象的方法中表示当前对象本身,如果通过对象调用一个方法,那么该对象会自动传入到当前方法的第一个参数中
  • self并不是关键字,只是一个用于接受对象的普通参数,理论上可以用任何一个普通变量名代替
  • 方法中有self形参的方法成为非绑定类的方法,可以通过对象访问,没有self的是绑定类的方法,只能通过类访问
  • 使用类访问绑定类的方法时,如果类方法中需要访问当前类的成员,可以通过__class__成员名
class Teacher():
    name = "cjl"
    age = 18
    
    def say(self):
        self.name = "aaa"
        self.age = "19"
        print("my name is {}".format(self.name))
        #调用类内的成员时需要使用__class__
        print("my age is {}".format(__class__.age))
    def sayAgain():
        print(__class__.name)
        print(__class__.age)
        print("hello")
        
t = Teacher()
t.say()
#调用绑定类函数使用类名
Teacher.sayAgain()

#执行结果:
'''
my name is aaa
my age is 18
cjl
18
hello
'''

④五种下划线:

  • _:用于临时或无意义变量的名称
  • _xxx:命名约定,说明该属性或方法仅供内部使用,但解释器不会强制执行
  • xxx_:避免声明的变量和关键字冲突
  • __xxx:用于声明属性和方法的私有化,解释权强制执行
  • __xxx__:Python自带的魔术方法,应避免自己声明该命名方式

⑤__init__构造函数:

  • python自带的内置函数具有特殊的函数,使用双下划线包起来的【魔术方法】
  • 是一个初始化的方法用来定义实例属性和初始化数据的,在创建对象的时候自动调用,不用手动去调用
  • 利用传参的机制可以让我们定义功能更加强大并且方便的类
class People():
    def __init__(self,name,age):
        self.name = name
        self.age = age
cjl = People('陈家霖',18)
print('我是{0}今年{1}岁'.format(cjl.name, cjl.age))

#执行结果:
'''
我是陈家霖今年18岁
'''
  • self指的是类实例对象本身,相当于java的this

⑥魔术方法:

  • __name__:显示当前的类名,常用于确保只有单独运行该模块时,此表达式才成立,才可以进入此判断语法,执行其中的测试代码
if __name__ == '__main__':
    ...
  • __all__:在使用from xxx import *导入模块时,不会导入__all__=[]外的方法,但import xxx不受影响
  • __str__:在将对象转换成字符串,相当于java的toString
class People():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        return '我是{0}今年{1}岁'.format(self.name, self.age)
cjl = People('陈家霖',18)
print(cjl)

#执行结果:
'''
我是陈家霖今年18岁
'''
  • __new__:优先 __init__初始化方法被调用,第一个参数默认为cls
class Person(object):
    def __init__(self, name, age):
        print('执行__init__')
        self.name = name
        self.age = age
    def __new__(cls, name, age):
        print('执行__new__')
        return super(Person, cls).__new__(cls)
    def __str__(self):
        return '<Person: %s(%s)>'%(self.name, self.age)
cjl = Person('cjl', 18)
print(cjl)

#执行结果:
'''
执行__new__
执行__init__
<Person: cjl(18)>
'''
  • __mro__:用于显示类的继承关系
class D():
    def play(self):
        print("'D'类的play")
class C(D):
    def play(self):
        print("'C'类的play")
class B(D):
    pass
class A(B,C):
    pass
demo = A()
demo.play()
print(A.__mro__)

#执行结果:
'''
'D'类的play
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)
'''
  • __dict__:用于查看类的所有属性,以字典形式显示
class People():
    def __init__(self,name,age):
        self.name = name
        self.age = age
cjl = People('cjl',18)
print(cjl.__dict__)

#执行结果:
'''
{'name': 'cjl', 'age': 18}
'''

⑦析构方法:

  • __del__:和__init__一样自动执行,用于释放对象实现资源回收,当一个对象调用后,自动执行清理该对象;也可使用del 对象名手动清理
class People():
    def __init__(self,name):
        self.name = name
        print("我是 %s 执行构造方法"%name)
    def __del__(self):
        print("执行析构方法,回收对象")
cjl = People("cjl")
print("--------使用手动清理--------")
del cjl  # 手动清理
print(cjl)

#执行结果:
'''
我是 cjl 执行构造方法
--------使用手动清理--------
执行析构方法,回收对象
NameError: name 'cjl' is not defined
'''

⑧继承:

  • 单继承:一个子类继承一个父类(找亲爹)
class Person():
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def eat(self):
        print('吃饭...')
class Men(Person):
    def __init__(self, name, age, height):
        super().__init__(name,age)
        self.height = height
    def play(self):
        print('玩儿...')
    def __str__(self):
        return '我是{}今年{}岁,身高{}'.format(self.name,self.age,self.height)
cjl = Men('cjl',18,183)
print(cjl, '\n调用父类方法:')
cjl.eat()

#执行结果:
'''
我是cjl今年18岁,身高183 
调用父类方法:
吃饭...
'''
  • 多继承:一个子类继承多个父类(认干爹)
class A():
    def a(self):
        print("A:我是C类它祖先类")
    pass
class B(A):
    def b(self):
        print("B:我是C类它父类")
    pass
class C(B):
    pass
num = C()
num.a()
num.b()
print(C.__mro__)

#执行结果:
'''
A:我是C类它祖先类
B:我是C类它父类
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
'''

⑨重写:

  • 所谓重写,就是在子类中有一个和父类一模一样的方法,即子类的方法会覆盖父类的方法
class Dog():
    def __init__(self,name,color):
        self.name = name
        self.color = color
    def bark(self):
        print("父类:汪汪汪的叫...")
class HaShiQi(Dog):
    def __str__(self):
        return '这一只 {0} 的狗叫 {1} '.format(self.color,self.name)
    def bark(self):
        # 重写父类方法
        print("子类:嗷嗷嗷的叫...")
hsq = HaShiQi('哈士奇','白色')
print(hsq)
hsq.bark()

#执行结果:
'''
这一只 白色 的狗叫 哈士奇 
子类:嗷嗷嗷的叫...
'''

⑩多态:

  • 多态的实现需要遵循两个条件:
    • 继承、多态发生在父类和子类之间
    • 重写、子类重写父类的方法
class Animals:
    def say_hello(self):
        print("我是一只小动物...")
class People:
    def say_hello(self):
        print("我是人...")
class Pig(Animals):
    def say_hello(self):
        print("我是可爱的小猪.")
class Cat(Animals):
    def say_hello(self):
        print("我是呆萌的小猫.")
class Dog(Animals):
    def say_hello(self):
        print("我是忠诚的小狗.")
class Student(People):
    def say_hello(self):
        print("我是三年级的小朋友.")
def commonInvoke(obj):
    obj.say_hello()
listObj = [Pig(),Cat(),Dog(),Student()]
for item in listObj:
    commonInvoke(item)
    
#执行结果:
'''
我是可爱的小猪.
我是呆萌的小猫.
我是忠诚的小狗.
我是三年级的小朋友.
'''

⑪类属性和实例属性:

  • 类属性是可以被类对象和实例对象共同访问使用的
  • 实例属性只能由实例对象所访问
class Person:
    age = 18
    def __init__(self,name):
        self.name = name
cjl = Person('cjl')
print(cjl.name)
print(Person.name)

#执行结果:
'''
实例对象: 18 cjl
类对象: 18
AttributeError: type object 'Person' has no attribute 'name'
'''

⑫类方法和静态方法:

  • 类方法用@classmethod来修饰,类方法的第一个参数对象是cls,虽然也能通过实例访问,但不推荐这样调用
class Person:
    people = 'cjl'
    @classmethod
    def get_name(cls):
        return cls.people
    @classmethod
    def change_name(cls,name):
        cls.people = name
print('类方法调用:%s'%(Person.get_name()))
p = Person()
print('实例对象调用(不推荐):%s'%(p.get_name()))
print('--------------修改之后----------------')
Person.change_name('lxl')
print(Person.get_name())

#执行结果:
'''
类方法调用:cjl
实例对象调用(不推荐):cjl
--------------修改之后----------------
lxl
'''
  • 静态方法用@staticmethod来修饰,静态方法可以不带参数,使用类和实例均可调用
import time
class TimeText:
    @staticmethod
    def time():
        return time.strftime('%H:%M:%S',time.localtime())

print('类对象调用:',TimeText.time())
demo = TimeText()
print('实例对象调用:',demo.time())

#执行结果:
'''
类对象调用: 09:44:47
实例对象调用: 09:44:47
'''

⑬私有化属性:

  • 在属性前加__,私有化后在外部不能调用,子类不能继承
class Person:
    def __init__(self):
        self.__name = 'cjl'
        self.age = 18
    def __str__(self):
        return '我是{0}今年{1}岁了'.format(self.__name, self.age)
class Men(Person):
    def printInfo(self):
        # 无法继承父类的私有化属性
#         print(self.name)
        print(self.age)
p = Person()
print(p)
# 无法在外部访问私有化属性
# print(p.__name)
men = Men()
men.printInfo()

#执行结果:
'''
我是cjl今年18岁了
子类继承父类: 18
'''
  • 私有化方法:
    • 和私有化属性一样,在方法前加__,私有化后在外部不能调用,子类不能继承

⑭property属性函数:

  • 使用property属性函数,用于调用和修改私有化属性
class Person:
    def __init__(self):
        self.__age = 18
    def get_age(self):
        return self.__age
    def set_age(self,age):
        if age < 0:
            print("年龄有误")
        else:
            self.__age = age
    age = property(get_age,set_age)
cjl = Person()
cjl.age = 19
print('修改后的年龄:',cjl.age)

#执行结果:
'''
修改后的年龄: 19
'''

⑮装饰器:

  • 用于调用和修改私有属性,用关键字@property@xxx.setter进行装饰,推荐使用该方法
class Person:
    def __init__(self):
        self.__age = 18
    @property
    def age(self):
        return self.__age
    @age.setter
    def age(self,age):
        if age < 0:
            print("年龄有误")
        else:
            self.__age = age
cjl = Person()
cjl.age = 19
print('修改后的年龄:',cjl.age)

#执行结果:
'''
修改后的年龄:19
'''

⑯单例模式:

  • 确保一个类只有一个实例的存在(类似win系统的回收站)
  • 实现方式一:通过类属性保存初次创建的实例对象,如果存在就返回保存的,没有就创建新的实例对象
class DataBase(object):
    _instance = None
    def __init__(self, name, age):
        print(name, age)
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance=super(DataBase,cls).__new__(cls)
        return cls._instance
db1 = DataBase('cjl',18)
print(id(db1))
db2 = DataBase('lxl',15)
print(id(db2))

#执行结果:
'''
cjl 18
2488840593520
lxl 15
2488840593520
'''
  • 实现方式二:只执行一次init方法,通过类变量进行标记控制
class Demo(object):
    __instance = None
    __isinit = True
    def __init__(self, name, age):
        if Demo.__isinit:
            self.name = name
            self.age = age
            __isinit = False
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance=super(Demo,cls).__new__(cls)
            return cls.__instance
        else:
            return cls.__instance
d1 = Demo('cjl',18)
print(id(d1), d1.name,d1.age)
d2 = Demo('lxl',15)
print(id(d2), d2.name,d2.age)

#执行结果:
'''
2488816354400 cjl 18
2488816354400 lxl 15
'''

⑰动态绑定属性方法:

  • 动态添加类属性、方法属性
class People:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        return '{}今年{}岁了'.format(self.name,self.age)

cjl = People('cjl',18)
People.sex = '男'
print(cjl)
print("动态添加类属性:性别,",cjl.sex)

#执行结果:
'''
cjl今年18岁了
动态添加类属性:性别, 男
'''
  • 动态绑定类方法
import types
def textMothend(self):
    print('{}今年{}岁了,性别:{}'.format(self.name,self.age,self.sex))
@classmethod
def classmethodTest(cls):
    print("类方法...")
@staticmethod
def staticmethodTest():
    print("静态方法...")
class People:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        return '{}今年{}岁了'.format(self.name,self.age)

cjl = People('cjl',18)
People.sex = '男'
print(cjl)
print("动态添加类属性:性别 -",cjl.sex)
cjl.printInfo = types.MethodType(textMothend,cjl) #动态绑定方法
print("---------------动态绑定后-------------")
cjl.printInfo()
# 绑定类方法 
People.TestMethod = classmethodTest
print("通过类调用:",end='\t\t')
People.TestMethod()
print("通过实例对象调用:",end='\t')
cjl.TestMethod()
# 绑定静态方法 
People.TestMethod = staticmethodTest
print("通过类调用:",end='\t\t')
People.TestMethod()
print("通过实例对象调用:",end='\t')
cjl.TestMethod()

#执行结果:
'''
cjl今年18岁了
动态添加类属性:性别 - 男
---------------动态绑定后-------------
cjl今年18岁了,性别:男
通过类调用:		类方法...
通过实例对象调用:	类方法...
通过类调用:		静态方法...
通过实例对象调用:	静态方法...
'''

⑱__slots__:

  • __slots__ = ():后跟元组,类型是字符串
    • 限制实例添加的属性,括号内为空时,则不允许添加任何属性;
    • 节省空间,使用后则类属性不会被存放在__dict__内,所以无法使用__dict__访问全部类属性;
    • 继承时子类不受影响,但如果子类也声明该方法时,则也会继承父类的属性限制
class Person(object):
    # 添加属性限制
    __slots__ = ('name','age','sex')
    def __init__(self):
        pass
    def __str__(self):
        return '{}........{}'.format(self.name,self.age)
class Men(Person):
    __slots__ = ('school')
    def __init__(self):
        pass
    def __str__(self):
        return '{}....{}....{}'.format(self.name,self.school,self.age)
    pass
cjl = Person()
cjl.name = 'cjl'
cjl.age = 19
# cjl.school = 'sqxy' # 未在属性限制范围内,所以报错
print(cjl)
cjl.sex = '男'
lxl = Men()
lxl.name = 'lxl'
lxl.age = 15
lxl.school = '七中'
print(lxl)

#执行结果:
'''
cjl........19
lxl....七中....15
'''


这篇关于python-面向对象的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程