python类的属性和对象的属性

一.类的属性和对象的属性

#定义类
class Fish:
    #类的属性
    name = "美人鱼"
    #对象的属性
    def __init__(self,weight):
        self.weight = weight

    def swim(self):
        print("我是一只鱼,游啊游!")
#创建对象
fish = Fish(80)
f1 = Fish(100)

#访问类的属性
print(Fish.name)
print(fish.name)


#访问对象的属性
print(fish.weight)
#print(Fish.weight)   #类不能访问对象的属性

'''
    访问类的属性和对象的属性的总结:
        1.类的属性可以使用类名访问(推荐)    类的属性也可以通过对象访问(不推荐)
        2.对象的属性可以使用对象访问(推荐)   对象的属性不可以通过类名访问(报错)
        3.在项目中 类的属性一般通过类名访问    对象的属性一般通过对象访问
'''

#修改类的属性
Fish.name = "虞美人"
fish.name = "草鱼"    #通过对象去修改类的属性时,不是对象修改了类的属性,只是给当前对象动态的添加了一个属性.
print(Fish.name)
print(fish.name)
print(f1.name)       #其他对象访问的还是类原来的属性    #虞美人

#修改对象的属性
fish.weight = 98
Fish.weight = 107
print(fish.weight)
print(Fish.weight)

'''
    修改类的属性和对象的属性的总结:
        1.类可以修改类的属性   对象在修改类的属性的时候,其实是动态的给当前对象添加了一个属性.其他的对象不能访问修改后的值.
        2.对象可以修改对象的属性    类也可以修改对象的属性.
        3.在项目中  一般情况下,通过类名去修改类的属性   通过对象名去修改对象的属性.
'''

二、封装

1.概念

广义的封装:函数和类的定义本身,就是封装的体现

狭义的封装:一个类的某些属性,在使用的过程 中,不希望被外界直接访问,而是把这个属性给作为私有的【只有当前类持有】,然后暴露给外界一个访问的方法即可【间接访问属性】

封装的本质:就是属性私有化的过程

封装的好处:提高了数据的安全性,提高了数据的复用性

2.属性私有化和方法私有化

如果想让成员变量不被外界直接访问,则可以在属性名称的前面添加两个下划线__,成员变量则被称为私有成员变量

私有属性的特点:只能在类的内部直接被访问,在外界不能直接访问

代码演示:

'''
下面的案例是:公有属性和公有方法,在任意位置可以直接访问
class Girl:
    def __init__(self,name,sex,age):
        self.name = name
        self.sex  = sex
        self.age = age

    def say(self):
        print(self.name,"说:帅哥帮个忙呗!")

hong = Girl("小红","美女",18)
hong.say()
print(hong.sex)
print(hong.age)

'''

'''
私有属性和私有方法

'''
class Girl:
    def __init__(self,name,sex,age):
        self.name = name
        self.sex  = sex
        #比如女孩的年龄是秘密,在外面不能轻易地访问,需要设置为私有属性
        '''
            私有属性:
                1.写法:在属性的前面加两个下划线  __age
                2.用法:只能在类的内部进行访问,不能在类的外部进行访问
        '''
        self.__age = age

    def say(self):
        print(self.name,"说:帅哥帮个忙呗!")

    #在类的内部可以访问私有属性
    def sayAge(self,friend):
        if friend == "熊明":
            print(f"{self.name},偷偷地告诉她男友说,她的年龄是:{self.__age}")
        else:
            print("女生的年龄是秘密不知道吗?活该你单身!")
    '''
        私有方法:
            1.写法:在方法名的前面加上两个下划线  __kiss
            2.用法:只能在类的内部访问,不能在类的外部访问.
    '''
    def __kiss(self):
        print("一吻定终身")

    #在类中可以访问私有方法
    def love(self,guan):
        if guan == "恋爱关系":
            self.__kiss()
        else:
            print("不能随便kiss,担心中毒")

hong = Girl("小红","美女",18)
hong.say()
print(hong.sex)
#print(hong.age)   #'Girl' object has no attribute 'age'  会报错
hong.sayAge("熊明")
#hong.__kiss()    #私有方法在类的外部不能直接访问,会报错

hong.love("好基友")
hong.love("恋爱关系")

3.get函数和set函数

get函数和set函数并不是系统的函数,而是自定义的,为了和封装的概念相吻合,起名为getXxx和setXxx

get函数:获取值

set函数:赋值【传值】

代码演示:

#第一种:通过自定义的get和set函数去访问私有属性和设置私有属性
class Girl:
       def __init__(self,name,age):
           self.name = name
           self.__age = age
   
       #通过get函数访问私有属性  命名规则: get + 私有属性名 (属性名首字母大写)
       def getAge(self):
           return self.__age

       #通过set函数设置私有属性, 命名规则: set + 私有属性名(属性名首字母大写)
       def setAge(self,age):
       	self.__age = age
   lan = Girl("小兰",19)
   print(lan.name)
   #print(lan.__age)
   lan.__age = 21  #在类的外部不能直接访问私有属性和修改私有属性的值
   lan.setAge(21)
   print(lan.getAge())
   
   
   # 书写私有属性age的get函数和set函数【通过自定义的函数进行私有属性的赋值和获取值,暴露给外界】
    
   #总结:通过将属性私有化之后,然后提供get函数和set函数,外部代码就不能随意更改成员变量的值,这样在一定程度上保证了数据的安全性

4.@property装饰器

装饰器的作用:可以给函数动态添加功能,对于类的成员方法,装饰器一样起作用

Python内置的@property装饰器的作用:将一个函数变成属性使用

@property装饰器:简化get函数和set函数

使用:@property装饰器作用相当于get函数,同时,会生成一个新的装饰器@属性名.settter,相当于set函数的作用

作用:使用在类中的成员函数中,可以简化代码,同时可以保证对参数做校验

代码演示:

class Girl:
       def __init__(self,name,age):
           self.name = name
           self.__age = age
   '''
       # 通过get函数访问私有属性  命名规则: get + 私有属性名 (属性名首字母大写)
       def getAge(self):
       return self.__age
   
       # 通过set函数设置私有属性, 命名规则: set + 私有属性名(属性名首字母大写)
       def setAge(self, age):
           self.__age = age
       '''
       #通过@property 装饰器 获取私有属性  相当于 getAge()
   	@property
       def age(self):
           return self.__age
   
   #通过 装饰器 设置私有属性时,  @ + 私有属性名 + .setter
       @age.setter
       def age(self,age):
           self.__age = age
   
   hua = Girl("小花",28)
print(hua.age)     #通过装饰器在外部获取私有属性时,写法是: 对象名.私有属性名
   hua.age = 22       #在此处相当于 调用了 setAge()方法
   print(hua.age)

三、类方法和静态方法

类方法:使用@classmethod装饰器修饰的方法,被称为类方法,可以通过类名调用,也可以通过对象调用,但是一般情况下使用类名调用

静态方法:使用@staticmethod装饰器修饰的方法,被称为静态方法,可以通过类名调用,也可以通过对象调用,但是一般情况下使用类名调用

代码演示:

class Animal:
    #类属性
    name = "牧羊犬"
    def __init__(self,name,sex):
        self.name = name
          self.sex = sex
      '''
        类的方法:
            1.通过@classmethod装饰器修饰的方法就是类方法
            2.可以使用类名或者对象名都可以调用类方法.   一般情况下使用类名调用类方法(节省内存)
            3.没有self,不可以使用类中其他对象的属性和方法(包括私有属性和私有方法)
              4.可以调用类属性和类方法,静态方法.通过cls调用
            5.形参的名字cls是class的简写,可以更换 只是一个约定俗称的写法而已
            6.cls表示的是当前类
    '''
    @classmethod
    def run(cls):
        print("我是属于类的方法")
        print(cls.name)
        print(cls == Animal)   #cls 相当于当前的类


      '''
          静态方法:通过@staticmethod 装饰器修饰的方法
              1.通过类名或者对象都可以调用静态方法
            2.没有self.不可以使用类中其他对象的属性和方法.(包含私有属性和私有方法)
              3.形式参数中没有cls,不建议使用类属性\类方法\静态方法
              4.静态方法一般是一个单独的方法,只是写在类中
      '''
    @staticmethod
    def eat():
        print("我是吃东西的静态方法")

Animal.run()   #通过类调用类方法
  dog = Animal("中华土狗","公")
#dog.run()    #通过对象调用类方法

Animal.eat()   #通过类名调用静态方法
dog.eat()      #通过对象调用静态方法

总结:实例方法【成员方法】、类方法以及静态方法之间的区别

a.语法上

​ 实例方法:第一个参数一般为self,在调用的时候不需要传参,代表的是当前对象【实例】

​ 静态方法:没有特殊要求

​ 类方法:第一个参数必须为cls,代表的是当前类

b.在调用上

​ 实例方法:只能对象

​ 静态方法:对象 或者 类

​ 类方法:对象 或者 类

c.在继承上【相同点】

​ 实例方法、静态方法、类方法:当子类中出现和父类中重名的函数的时候,子类对象调用的是子类中的方法【重写】

代码演示:

class SuperClass(object):
@staticmethod
def show():
  print("父类中的静态方法")

@classmethod
def check(cls):
  print("父类中的类方法")

class SubClass(SuperClass):
pass

s = SubClass()
s.show()
s.check()

注意:注意区分三种函数的书写形式,在使用,没有绝对的区分

四、类中的常用属性

__name__
    通过类名访问,获取类名字符串
    不能通过对象访问,否则报错
​
__dict__
    通过类名访问,获取指定类的信息【类方法,静态方法,成员方法】,返回的是一个字典
    通过对象访问,获取的该对象的信息【所有的属性和值】,,返回的是一个字典
​
__bases__
    通过类名访问,查看指定类的所有的父类【基类】

代码演示:

class Animal(object):
def __init__(self,arg):
  super(Animal, self).__init__()
  self.arg = arg


class Tiger(Animal):
age = 100
height = 200

def __init__(self,name):
  #super(Tiger, self).__init__(name)
  self.name = name

def haha(self):
  print("haha")

@classmethod
def test(cls):
  print("cls")

@staticmethod
def show():
  print("show")


if __name__ == "__main__":

#1.__name__
print(Tiger.__name__)  #Tiger

t = Tiger("")
#print(t.__name__)  #AttributeError: 'Tiger' object has no attribute '__name__'

#2.__dict__
print(Tiger.__dict__)  #类属性,所有的方法
print(t.__dict__)   #实例属性

#3.__bases__,获取指定类的所有的父类,返回的是一个元组
print(Tiger.__bases__)

五、继承【extends】

1.概念

如果两个或者两个以上的类具有相同的属性或者成员方法,我们可以抽取一个类出来,在抽取的类中声明公共的部分

​ 被抽取出来的类:父类,基类,超类,根类

​ 两个或者两个以上的类:子类,派生类

​ 他们之间的关系:子类 继承自 父类

注意:

​ a.object是所有类的父类,如果一个类没有显式指明它的父类,则默认为object

​ b.简化代码,提高代码的复用性

2.单继承

2.1使用

简单来说,一个子类只能有一个父类,被称为单继承

语法:

父类:

class 父类类名(object):

​ 类体【所有子类公共的部分】

子类:

class 子类类名(父类类名):

​ 类体【子类特有的属性和成员方法】

说明:一般情况下,如果一个类没有显式的指明父类,则统统书写为object

代码演示:

person.py文件【父类】

#1.定义父类
class Person(object):
 #构造函数【成员变量】
 def __init__(self,name,age):
     self.name = name
     self.age = age


 #成员方法
 def show(self):
     print("show")

 def __fun(self):
     print("fun")

子类:
#2.定义子类
class Worker(Person):
 #构造函数【成员变量】
 def __init__(self,name,age,job):
     """
     self.name = name
     self.age = age
     """
     self.job = job

     #6.在子类的构造函数中调用父类的构造函数【从父类中继承父类中的成员变量】
     #方式一:super(当前子类,self).__init__(属性列表)
     #super(Worker, self).__init__(name,age)
     #方式二:父类名.__init__(self,属性列表)
     Person.__init__(self,name,age)
     #方式三:super().__init__(属性列表)
     #super().__init__(name,age)


 #成员方法
 def work(self):
     print("work")   
    
#定义子类
class Student(Person):
 # 构造函数【成员变量】
 def __init__(self, name, age, score):

     Person.__init__(self,name,age)
     self.score = score

 # 成员方法
 def study(self):
     print("study") 

总结:

继承的特点:

​ a.子类对象可以直接访问父类中非私有化的属性

​ b.子类对象可以调用父类中非私有化的成员方法

​ c.父类对象不能访问或者调用子类 中任意的内容

继承的优缺点:

优点:

​ a.简化代码,减少代码的冗余

​ b.提高代码的复用性

​ c.提高了代码的可维护性

​ d.继承是多态的前提

缺点:

​ 通常使用耦合性来描述类与类之间的关系,耦合性越低,则说明代码的质量越高

​ 但是,在继承关系中,耦合性相对较高【如果修改父类,则子类也会随着发生改变】

3.多继承

一个子类可以有多个父类

语法:

class 子类类名(父类1,父类2,父类3.。。。):

​ 类体

代码演示:

父亲类:
class Father(object):
 	def __init__(self,money):
     	self.money = money

 	def play(self):
     	print("playing")

 	def fun(self):
     	print("father中的fun")
母亲类:
class Mother(object):
 	def __init__(self,faceValue):
    	 self.faceValue = faceValue

	 def eat(self):
    	 print("eating")

	 def fun(self):
    	 print("mother中的fun")
            

#定义子类,有多个父类
class Child(Mother,Father):
 	def __init__(self,money,faceValue,hobby):
    		 #调用父类中的构造函数
     		Father.__init__(self,money)
     		Mother.__init__(self,faceValue)
     		self.hobby = hobby

 	def study(self):
     	print("study")

六、多态【了解】

一种事物的多种体现形式,函数的重写其实就是多态的一种体现

在Python中,多态指的是父类的引用指向子类的对象

代码演示:

#父类
class Animal(object):
 	pass

#子类
class Dog(Animal):
 	pass

class Cat(Animal):
 	pass

#定义变量
a = []   #a是list类型
b = Animal()  #b是Animal类型
c = Cat()  #c是Cat类型

#isinstance():判断一个对象是否属于某种类型【系统还是自定义的类型】
print(isinstance(a,list))
print(isinstance(b,Animal))
print(isinstance(c,Cat))

print(isinstance(c,Animal))  #True
print(isinstance(b,Dog))   #False

#结论:子类对象可以是父类类型,但是,父类的对象不能是子类类型

总结:

​ 简化代码,提高代码的可读性,可维护性

七、单例设计模式【扩展】

1.概念

什么是设计模式

​ 经过已经总结好的解决问题的方案

​ 23种设计模式,比较常用的是单例设计模式,工厂设计模式,代理模式,装饰模式

什么是单例设计模式

​ 单个实例【对象】

​ 在程序运行的过程中,确保某一个类只能有一个实例【对象】,不管在哪个模块中获取对象,获取到的都是同一个对象

​ 单例设计模式的核心:一个类有且仅有一个实例,并且这个实例需要应用在整个工程中

2.应用场景

实际应用:数据库连接池操作-----》应用程序中多处需要连接到数据库------》只需要创建一个连接池即可,避免资源的浪费

3.实现

3.1模块

Python的模块就是天然的单例设计模式

模块的工作原理:

​ import xxx,模块被第一次导入的时候,会生成一个.pyc文件,当第二次导入的时候,会直接加载.pyc文件,将不会再去执行模块源代码

3.2使用new

__new__():实例从无到有的过程【对象的创建过程】

代码演示:

class Singleton(object):
 #类属性
 instance = None

 #类方法
 @classmethod
 def __new__(cls, *args, **kwargs):
     #如果instance的值不为None,说明已经被实例化了,则直接返回;如果为NOne,则需要被实例化
     if not cls.instance:
         cls.instance = super().__new__(cls)

     return cls.instance

class MyClass(Singleton):
 pass

#当创建对象的时候自动被调用
one = MyClass()
two = MyClass()

print(id(one))
print(id(two))

print(one is two)

  • 4
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值