Python入门笔记(二)(下)

简介: Python入门笔记(二)

10.5 return返回值


函数并非总是直接显示输出,相反,它可以处理一些数据,并返回一个或一组值。


函数返回的值被称为返回值。


在函数中,可使用return语句将值返回到调用函数的代码行。


返回值让你能够将程序的大部分繁重工作移到函数中完成,从而简化主程序。


例1: 返回简单值


def get_formatted_name(first_name, last_name):
    """返回整洁的姓名"""
    full_name = first_name + " " + last_name
    return full_name.title()
musician = get_formatted_name('z', 'db')
print(musician)


Z Db


(1)如果函数没有返回值【函数执行完毕之后,不需要给调用处提供数据】,return可以省略不写


(2)函数的返回值,如果是1个,直接返回类型


(3)函数的返回值,如果是多个,返回的结果为元组


函数在定义时,是否需要返回值,视情况而定


def fun1():
    print('hello')
    # return
fun1()
def fun2():
    return 'hello'
res = fun2()
print(res)
def fun3():
    return 'hello', 'world'
print(fun3())


hello
hello
('hello', 'world')


例2: 返回字典


def your_name(first_name, last_name):
    """返回一个字典,其中包含有关一个人的信息"""
    person = {'姓': first_name, '名': last_name}
    return person
name = your_name('z', 'db')
print(name)    


{'姓': 'z', '名': 'db'}


例3: 字典添加元素


def your_name(first_name, last_name, age=' '):
    """返回一个字典,其中包含有关一个人的信息"""
    person = {'姓': first_name, '名': last_name}
    if age:                   # 有age就赋值,没有不赋值
        person['年龄'] = age   # 将输入的age赋值给字典键age对应的值
    return person
name = your_name('z', 'db', age=22)
print(name)


{'姓': 'z', '名': 'db', '年龄': 22}


例4:结合使用函数和while循环


版本一:无线循环,不能停止


def your_name(first_name, last_name):
    """返回整洁的姓名"""
    full_name = first_name + " " + last_name
    return full_name.title()
active = True
while active:
    print("请告诉我你的名字:")
    f_name = input("First name:")     # 输入的First anme 赋值给f_name
    l_name = input("Last name:")      # 输入的Last name  赋值给l_name
    name = your_name(f_name, l_name)    # 调用定义的函数
    print("你好, " + name + "!")
    a = input("是否继续,输入quit可退出:")
    if a == 'quit':
        active = False 


请告诉我你的名字:
First name:hu
Last name:zhuzhu
你好, Hu Zhuzhu!
是否继续,输入quit可退出:hu
请告诉我你的名字:
First name:hu
Last name:zhuzhu
你好, Hu Zhuzhu!
是否继续,输入quit可退出:quit


函数作为返回值


例1: 实现一个可变参数的求和。


通常情况下,求和的函数是这样定义的:


def calc_sum(*args):
    ax = 0
    for n in args:
        ax = ax + n
    return ax


但是,如果不需要立刻求和,而是在后面的代码中,根据需要再计算怎么办?


可以不返回求和的结果,而是返回求和的函数:


def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum


当我们调用lazy_sum()时,返回的并不是求和结果,而是求和函数:


>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f
<function lazy_sum.<locals>.sum at 0x101c6ed90>


调用函数f时,才真正计算求和的结果:


>>> f()
25


10.6 导入模块,函数的几种方法


首先,将函数存储在模块中


  • 1、使用函数可以将代码块与主程序分离


  • 2、通过将函数存储在独立的文件中,可隐藏程序代码的细节,将重点放在程序的高层逻辑上。


1. import 模块名:导入整个模块


1.先创建模块,模块是扩展名为 .py的文件


pizza.py


def make_pizza(size, *toppings):
    """概述要制作的披萨"""
    print("\nMaking a " + str(size) +
          "-inch pizza with the following toppings:")
    for topping in toppings:
        print("- " + topping)


2.调用


import pizza
pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')


3.输出


Making a 16-inch pizza with the following toppings:
- pepperoni
Making a 12-inch pizza with the following toppings:
- mushrooms
- green peppers
- extra cheese


2. from 模块 import 函数:导入模块中特定的函数


正常调用模块使用函数


module_name.function_name()


你还可以导入模块中的特定函数


from module_name import function_name


通过用逗号分隔函数名,可根据需要从模块中导入任意数量的函数


form module_name import function_0, function_1, function_2


对于前面的making_pizza.py示例,如果只想要导入要使用的函数,代码将类似于下面这样:


from pizza import make_pizza
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')


3. 用as给函数指定别名


格式:form 模块 import 函数名 as 别名


如果要导入的函数的名称可能与程序中现有的名称冲突,或者函数的名称太长,可指定简短而独一无二的别名


from pizza import make_pizza as mp
mp(16, 'pepperoni')
mp(12, 'mushrooms', 'green peppers', 'extra cheese')


4. 用as给模块指定别名


格式:import 模块 as 模块别名


import pizza as p
p.make_pizza(16, 'pepperoni')
p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese') 


5. (*)导入模块中所有函数


使用星号(*) 导入模块中所有函数


from pizza import *
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')


import语句中的星号让python将模块pizza中的每个函数都复制到这个程序文件中


10.7 导入包


包是一个分层次的目录结构,它将一组功能相近的模块组织在一下


  • 作用:


1、代码规范


2、避免模块名称冲突


包和目录的区别:


  • 1、包含__init __.py文件的目录称为包


  • 2、目录里通常不包含__init __.py文件


创建包:


1、创建一个文件夹,用于存放相关的模块,文件夹的名字即包的名字


2、在文件夹中创建一个__init__.py的模块文件,内容可以为空


导入包模块


import 包名.模块名


起别名:


import 包名 as 别名


from  包名 import 模块名
from 包名.模块名 import 函数名/变量名



>>> import sys   # 这里直接导入包
>>> sys.path.append('C:\\Users\\zdb\\Desktop')
>>> import M1.Temperature   # 导入包里面的模块
>>> M1.Temperature.c2f(32)  # 使用包.模块.函数
89.6



10.8 if __name __ == ‘__main __’


以主程序形式运行


def c2f(cel):
    fah = cel * 1.8 +32
    return fah
def f2c(fah):
    cel = (fah - 32)/1.8
    return cel
def test():             #多了这个
    print('测试:0摄氏度 = %.2f华氏度' % c2f(0))
    print('测试:0华氏度 = %.2f摄氏度' % f2c(0))
if __name__ == '__main__':   #多了这个
    test()



第十一章 类class


类命名首字母大写


11.1 类对象、类属性、实例方法


1. 类对象class


面向对象最重要的概念就是类(Class)和实例(Instance)


类是属性和方法的封装


2. 类属性:类中方法外的变量称为类属性,被该类的所有对象所共享


# 类名有一个或多个单词组成,单词首字母大写,其余小写
class Student():  # Student为类的名称,
    native_pace = '吉林'  # 直接写在类里面的变量, 称为类属性


3. 实例方法


# 类名有一个或多个单词组成,单词首字母大写,其余小写
class Student():  # Student为类的名称,
    native_pace = '吉林'  # 直接写在类里面的变量, 称为类属性
    # 初试化方法
    def __init__(self, name, age):
        # self称为实例属性,这里进行了一个赋值操作,将局部变量name的值赋值给实例属性
        self.name = name
        self.age = age
    # 实例方法
    def eat(self):   # 类里面的函数称为方法,
        print('学生正在吃饭...')


11.2 静态方法:@staticmethod


静态方法:使用 @staticmethod 修饰的方法,使用类名直接访问的方法


# 类名有一个或多个单词组成,单词首字母大写,其余小写
class Student():  # Student为类的名称,
    native_pace = '吉林'  # 直接写在类里面的变量, 称为类属性
    # 初试化方法
    def __init__(self, name, age):
        # self称为实例属性,这里进行了一个赋值操作,将局部变量name的值赋值给实例属性
        self.name = name
        self.age = age
    # 实例方法
    def eat(self):   # 类里面的函数称为方法,
        print('学生正在吃饭...')
    # 静态方法
    @staticmethod
    def method():   # 这里不能写self
        print('我使用了statticmethod进行修饰,所以我是静态方法')


11.3 类方法:@classmethod


类方法:使用 @classmethod 修饰的方法。使用类名直接访问的方法


# 类名有一个或多个单词组成,单词首字母大写,其余小写
class Student:  # Student为类的名称,
    native_pace = '吉林'  # 直接写在类里面的变量, 称为类属性
    # 初试化方法
    def __init__(self, name, age):
        # self称为实例属性,这里进行了一个赋值操作,将局部变量name的值赋值给实例属性
        self.name = name
        self.age = age
    # 实例方法
    def eat(self):   # 类里面的函数称为方法,
        print('学生正在吃饭...')
    # 静态方法
    @staticmethod
    def method():   # 这里不能写self
        print('我使用了statticmethod进行修饰,所以我是静态方法')
    # 类方法
    @classmethod
    def cm(cls):  # 这里传入cls
        print('我是类方法,因为我使用了classmethod进行修饰')


11.4 类的实例化 (实例对象)


根据类来创建对象被称为实例化


语法:实例名 = 类名()


stu = Student()


有了实例,就可以调用类中的内容。


这里接着最上面的代码继续


# 创建Student类的对象
stu1 = Student('张三', 20)
stu1.eat()              # 对象名.方法名()
print(stu1.name)
print(stu1.age)
print('-----------------')
# 类名.方法名(对象)
Student.eat(stu1)       # 这个也可以


学生正在吃饭...
张三
20
-----------------
学生正在吃饭...


完整代码如下:


# 类名有一个或多个单词组成,单词首字母大写,其余小写
class Student():  # Student为类的名称,
    native_pace = '吉林'  # 直接写在类里面的变量, 称为类属性
    # 初试化方法
    def __init__(self, name, age):
        # self称为实例属性,这里进行了一个赋值操作,将局部变量name的值赋值给实例属性
        self.name = name
        self.age = age
    # 实例方法
    def eat(self):   # 类里面的函数称为方法,
        print('学生正在吃饭...')
    # 静态方法
    @staticmethod
    def method():   # 这里不能写self
        print('我使用了statticmethod进行修饰,所以我是静态方法')
    # 类方法
    @classmethod
    def cm(cls):  # 这里传入cls
        print('我是类方法,因为我使用了classmethod进行修饰')
# 类属性,类方法,静态方法
# 类属性:类中方法外的变量称为类属性,被该类的所有对象所共享
# 类方法:使用@classmethod修饰的方法。使用类名直接访问的方法
# 静态方法:使用@staticmethod修饰的主法,使用类名直接访问的方法
print(Student.native_pace)   # 访问类属性
# Student.cm()                  # 调用类方法
# Student.sm()                  # 调用静态方法
# 创建Student类的对象
stu1 = Student('张三', 20)
stu2 = Student('李四', 30)
print(stu1.native_pace)
print(stu2.native_pace)
Student.native_pace = '天津'
print(stu1.native_pace)
print(stu2.native_pace)
print('---------------类方法的使用方式--------------')
Student.cm()    # cls不需要传入
print('---------------静态方法的使用方式--------------')
Student.method()


动态绑定属性


class Student():  # Student为类的名称,
    native_pace = '吉林'  # 直接写在类里面的变量, 称为类属性
    # 初试化方法
    def __init__(self, name, age):
        # self称为实例属性,这里进行了一个赋值操作,将局部变量name的值赋值给实例属性
        self.name = name
        self.age = age
# 创建Student类的对象
stu1 = Student('张三', 20)
stu2 = Student('李四', 30)
stu2.gender = '女'   # stu2多了一个属性,而stu1没有
print(stu1.name, stu1.age)
print(stu2.name, stu2.age, stu2.gender)


张三 20
李四 30 女


动态绑定方法


class Student():  # Student为类的名称,
    native_pace = '吉林'  # 直接写在类里面的变量, 称为类属性
    # 初试化方法
    def __init__(self, name, age):
        # self称为实例属性,这里进行了一个赋值操作,将局部变量name的值赋值给实例属性
        self.name = name
        self.age = age
    # 实例方法
    def eat(self):   # 类里面的函数称为方法,
        print('学生正在吃饭...')
def show():
    print('定义在类之外的,称函数')
# 创建Student类的对象
stu1 = Student('张三', 20)
stu2 = Student('李四', 30)
stu1.show = show
stu1.show()


定义在类之外的,称函数


11.5 面向对象的三大特征:封装,继承,多态


1.封装:提高程序的安全性


  • 1、将数据(属性)和行为(方法)包装到类对象中。在方法内部对属性进行操作,在类对象的外部调用方法。这样,无需关心方法内部的具体实现细节,从而隔离了复杂度


  • 2、在python中没有专门的修饰符用于属性的私有,如果该属性不希望在类对象外部被访问,前边使用两个“_”


将一类事物的属性和行为抽象成一个类,使其属性私有化,行为公开化,
提高了数据的隐秘性的同时,使代码模块化。这样做使得代码的复用性更高。
意义:
1. 将属性和方法放到一起做为一个整体,然后通过实例化对象来处理;
2. 隐藏内部实现细节,只需要和对象及其属性和方法交互就可以了;
3. 对类的属性和方法增加 访问权限控制。


2.继承:提高代码的复用性


语法:


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


  • 1、如果一个类没有继承任何类,则默认继承object


  • 2、python支持多继承


  • 3、在定义子类时,必须在其构造函数中调用父类的构造函数




  • 让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。


创建子类的实例时,python首先需要完成的任务是给父类的所有属性赋值。为此,子类的方法 __ init__() 需要父类施以援手。


super()是一个特殊函数,帮助python将父类和子类关联起来。 这行代码让python调用ElectricCar的父类的方法__init__(),让ElectricCar实例包含父类的所有属性。


class Person(object):   # 也可以不写object
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def info(self):
        print('姓名:{0},年龄:{1}'.format(self.name, self.age))
# 定义子类
class Student(Person):
    def __init__(self, name, age, score):
        super().__init__(name, age)  # 调用父类的init方法,继承
        self.score = score           # 子类自己的属性
class Teacher(Person):
    def __init__(self, name, age, teacher_of_year):
        super().__init__(name, age)
        self.teacher_of_year = teacher_of_year
# 测试
stu = Student('Jack', 20, '1001')
stu.info()
teacher = Teacher('李四', 34, 20)
teacher.info()


姓名:Jack,年龄:20
姓名:李四,年龄:34


多继承


class A(object):
    pass
class B(object):
    pass
class C(A, B):  # 继承A和B
    pass


把类A的实例用作类B的属性


当添加类的细节越来越多时,可将类的一部分作为一个独立的类提取出来,将一个大类拆分成若干个小类。


例1


"""组合 """
class Turtle:           # 乌龟类
    def __init__(self, x):
        self.num = x
class Fish:             # 鱼类
    def __init__(self, y):
        self.num = y
class Pool:            # 水池类
    def __init__(self, x, y):    # x只乌龟,y个鱼
        self.turtle = Turtle(x)  # 乌龟
        self.fish = Fish(y)      # 鱼
    def print_num(self):
        print('水池里总共有乌龟 %d 只,小鱼 %d 条!' % (self.turtle.num, self.fish.num))
pool = Pool(1, 10)      # 乌龟1个,鱼10个
pool.print_num()       # 输出


水池里总共有乌龟 1 只,小鱼 10 条!


重写父类的方法


对于父类的方法,只要它不符合子类模拟的实物的行为,都可对其进行重写。为此,可在子类中定义一个这样的方法,即它与要重写的父类方法同名。这样,python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。


例1


class Animal(object):
    def run(self):
        print('Animal is running...')
class Dog(Animal):
    def run(self):
        print('Dog is running...')
    def eat(self):
        print('Eating meat...')
animal = Animal()
animal.run()
dog = Dog()
dog.run()


Animal is running...
Dog is running...



class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def info(self):
        print('姓名:{0},年龄{1}'.format(self.name, self.age))
# 定义子类
class Student(Person):
    def __init__(self, name, age, score):
        super().__init__(name, age)
        self.score = score
    def info(self):
        super().info()
        print('学号:{0}'.format(self.score))
class Teacher(Person):
    def __init__(self, name, age, teacher_of_year):
        super().__init__(name, age)
        self.teacher_of_year = teacher_of_year
    def info(self):
        super().info()
        print('教龄', self.teacher_of_year)
# 测试
stu = Student('张三', 20, '1001')
stu.info()    # 继承父类输出的姓名和年龄,子类自己多了学号
print('-------')
teacher = Teacher('李四', 34, 10)
teacher.info()


姓名:张三,年龄20
学号:1001
-------
姓名:李四,年龄34
教龄 10


# object类
# object类是所有类的父类,因此所有类都有object类的属性和方法
# 内置函数dir()可以查看指定对象所有属性
# object有一个__str__()方法,用于返回一个对于“对象的描述”,
# 对应于内置函数str()经常用于print()方法,帮我们查看对象的信息,
# 所以我们经常会对__str__()进行重写
class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def info(self):
        print('姓名:{0},年龄:{1}'.format(self.name, self.age))
    def __str__(self):
        return '姓名:{0},年龄:{1}'.format(self.name, self.age)
o = object()
p = Person('Jack', 20)
print(dir(o))
print(dir(p))
print(p)



class Student:
    pass
stu = Student()
print(dir(stu))
print(stu)


这里print(str)输出的是内存地址


['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
<__main__.Student object at 0x00000246F49EAEC8>


def __str __(self)


class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __str__(self):
        return '我的名字是{0},今年{1}岁了'.format(self.name, self.age)
stu = Student('张三', 20)
print(dir(stu))
print(stu)         # 默认调用__str__()这样的方法
print(type(stu))


['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'name']
我的名字是张三,今年20岁了
<class '__main__.Student'>


修改类的方法


class C:
    def x(self):
        print('X.man!')
c = C()
c.x()
c.x = 1   # 修改方法
print(c.x)


X.man!
1


修改属性的值


1、直接修改属性的值


class Car():    
     --snip--    #与上面相同
my_new_car = Car('audi', 'a4', 2016)        #创建实例
print(my_new_car.get_descriptive_name())    #调用属性
my_new_car.odometer_reading = 23
my_new_car.read_odometer()


2016 Audi A4
This car has 23 miles on it.


2、通过方法修改属性的值


如果有替你更新属性的方法,将大有裨益。这样,你就无需直接访问属性,而可将值传递给一个方法,由它在内部进行更新。


class Car():
    """一次模拟汽车的简单尝试"""
    def __init__(self, make, model, year):
        """初始化描述汽车的属性"""
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0     #初始化
    def get_descriptive_name(self):
        """返回整洁的描述性信息"""
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()
    def read_odometer(self):
        """打印一条指出汽车里程的消息"""
        print("This car has " + str(self.odometer_reading) + " miles on it.")
    def update_odometer(self, mileage):   #定义这个函数,用这个更新read_odometer函数
        """将里程表读数设置为指定的值"""
        self.odometer_reading = mileage
my_new_car = Car('audi', 'a4', 2016)        #创建实例
print(my_new_car.get_descriptive_name())    #调用属性
my_new_car.update_odometer(23)              #这里改了
my_new_car.read_odometer()


3、通过方法对属性的值进行递增


class Car():
    """一次模拟汽车的简单尝试"""
    def __init__(self, make, model, year):
        """初始化描述汽车的属性"""
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0     #初始化
    def get_descriptive_name(self):
        """返回整洁的描述性信息"""
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()
    def read_odometer(self):
        """打印一条指出汽车里程的消息"""
        print("This car has " + str(self.odometer_reading) + " miles on it.")
    def update_odometer(self, mileage):   #定义这个函数,用这个更新read_odometer函数
        """
        将里程表读数设置为指定的值
        禁止这里程表读数往回调
        """
        if mileage >= self.odometer_reading:   #禁止调的比原来小
            self.odometer_reading = mileage
        else:
            print("You can't roll back an odometer!")
    def increment_odometer(self, miles):
        """将里程表读数增加指定的量"""
        self.odometer_reading += miles
my_new_car = Car('audi', 'a4', 2016)        #创建实例
print(my_new_car.get_descriptive_name())    #调用属性    #2016 Audi A4
my_new_car.update_odometer(235000)
my_new_car.read_odometer()
my_new_car.increment_odometer(100)
my_new_car.read_odometer() 


2016 Audi A4
This car has 235000 miles on it.
This car has 235100 miles on it.


多态:提高程序的可扩展性和可维护性


  • 简单地说,多态就是“具有多种形态”,它指的是:即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用方法,在运行过程中根据变量所引用对象的类型,动态决定调用哪个对象中的方法


class Animal(object):
    def eat(self):
        print('动物要吃东西')
class Dog(Animal):
    def eat(self):
        print('狗吃肉')
class Cat(Animal):
    def eat(self):
        print("猫吃鱼")
class Person(object):
    def eat(self):
        print('人吃五谷杂粮')
def fun(animal):
    animal.eat()
fun(Dog())
fun(Cat())
fun(Animal())
print('--------------')
fun(Person())


狗吃肉
猫吃鱼
动物要吃东西
--------------
人吃五谷杂粮


  • 问: self是什么?


面向对象编程


python中的self相当于C++里面的this指针


  • 问:什么是绑定?


python严格要求方法需要有实例才能被调用,这种限制其实就是python所谓的绑定概念


11.6 私有变量(private)限制访问


外部访问属性、修改属性


class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score
bart = Student('Bart Simpson', 59)
print(bart.score)
bart.score = 99
print(bart.score)


59
99


private:私有变量


  • 如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问,所以,我们把Student类改一改:


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))


错误实例:


class Person:
    __name = 'zdb'   # 私有变量
p = Person()
print(p.__name)


AttributeError: 'Person' object has no attribute '__name'


访问私有变量方法


  • 但是如果外部代码要获取name和score怎么办?可以给Student类增加get_name和get_score这样的方法:


  • 如果又要允许外部代码修改score怎么办?可以再给Student类增加set_score方法:


你也许会问,原先那种直接通过bart.score = 99也可以修改啊,为什么要定义一个方法大费周折?因为在方法中,可以对参数做检查,避免传入无效的参数:


class Student:
    def __init__(self, name, age):
        self.name = name
        self.__age = age  # 不希望在类的外部被使用,不是不能,是不希望
    def show(self):
        print(self.name, self.__age)
stu = Student('张三', 20)
print(stu.name)
# print(stu.__name)  ## 这个不能
# print(dir(stu))
# 完全靠自觉性不访问
print(stu._Student__age)  # 在类的外部可以通过_Student__age进行访问


例:


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))
    def get_name(self):
        return self.__name
    def get_score(self):
        return self.__score
    def set_score(self, score):
        if 0 <= score <= 100:
            self.__score = score
        else:
            raise ValueError('bad score')
    def set_score(self, score):
        self.__score = score
bart = Student('Bart Simpson', 59)
print(bart._Student__name)
print(bart.get_name())
bart.print_score()
print(bart.get_score())


Bart Simpson
Bart Simpson
Bart Simpson: 59
59


例2


class Person:
    __name = 'zdb'
    def getName(self):        # 设置方法
        return self.__name    # 返回私有变量
p = Person()
print(p.getName())


zdb


11.7 特殊的属性和方法


特殊属性


名称 描述
__dict __ 获得类对象或实例对象所绑定的所有属性和方法的字典


class A:
    pass
class B:
    pass
class C(A, B):
    def __init__(self, name, age):
        self.name = name
        self.age = age
# 创建C类的对象
x = C('Jack', 20)     # x是C类型的一个实例对象
print(x.__dict__)
print(C.__dict__)     # 能看到属性和方法的字典
print('-------------------')
print(x.__class__)    # 输出对象所属于的类
print(C.__bases__)    # 输出C类的父类类型的元组
print(C.__base__)     # 谁写在继承括号的最前面就输出谁,类的基类
print(C.__mro__)      # 类的层次结构
print(A.__subclasses__())   # A的子类的列表


{'name': 'Jack', 'age': 20}
{'__module__': '__main__', '__init__': <function C.__init__ at 0x000001DEB40B7678>, '__doc__': None}
-------------------
<class '__main__.C'>
(<class '__main__.A'>, <class '__main__.B'>)
<class '__main__.A'>
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
[<class '__main__.C'>]


特殊方法


名称 描述
__len __() 通过重写__len __()方法,让内置函数len()的参数可以是自定义类型
__add __() 通过重写__add __()方法,可使用自定义对象具有“+”功能
__new __() 用于创建对象
__init __() 对创建的对象进行初始化


a = 20
b = 100
c = a + b
print(c)
d = a.__add__(b)    # 实现一样的加法功能
print(d)
class Student:
    def __init__(self, name):
        self.name = name
    def __add__(self, other):
        return self.name + other.name
    def __len__(self):
        return len(self.name)
stu1 = Student('Jack')
stu2 = Student('李四')
s = stu1 + stu2          # 有__add__方法后才能相加,没有会报错
print(s)
s = stu1.__add__(stu2)   # 这种方法也可以实现相加
print(s)
print('-----------------------')
lst = [11, 22, 33, 44]
print(len(lst))
print(lst.__len__())    # 这样也可以
print(len(stu1))


120
120
Jack李四
Jack李四
-----------------------
4
4
4


例:这个一点都看不懂


class Person(object):
    def __new__(cls, *args, **kwargs):
        print("__new__被调用执行了,cls的ID值为{0}".format(id(cls)))
        obj = super().__new__(cls)
        print('创建的对象的ID为:{0}'.format(id(obj)))
        return obj
    def __init__(self, name, age):
        print('__init__被调用了,self的ID值为{0}'.format(id(self)))
        self.name = name
        self.age = age
print('object这个类对象的ID为:{0}'.format(id(object)))
print('Person这个类对象的ID为{0}'.format(id(Person)))
# 创建Person类的实例对象
p1 = Person('张三', 20)
print('p1这个Person类的实例对象的ID:{0}'.format(id(p1)))


object这个类对象的ID为:140711006337840
Person这个类对象的ID为2219114295720
__new__被调用执行了,cls的ID值为2219114295720
创建的对象的ID为:2219148478536
__init__被调用了,self的ID值为2219148478536
p1这个Person类的实例对象的ID:2219148478536
目录
相关文章
|
3天前
|
Java 测试技术 持续交付
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
本文重点讲解如何搭建App自动化测试框架的思路,而非完整源码。主要内容包括实现目的、框架设计、环境依赖和框架的主要组成部分。适用于初学者,旨在帮助其快速掌握App自动化测试的基本技能。文中详细介绍了从需求分析到技术栈选择,再到具体模块的封装与实现,包括登录、截图、日志、测试报告和邮件服务等。同时提供了运行效果的展示,便于理解和实践。
20 4
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
|
4天前
|
Python
探索Python装饰器:从入门到实践
【10月更文挑战第32天】在编程世界中,装饰器是一种特殊的函数,它允许我们在不改变原有函数代码的情况下,增加额外的功能。本文将通过简单易懂的语言和实际案例,带你了解Python中装饰器的基础知识、应用以及如何自定义装饰器,让你的代码更加灵活和强大。
11 2
|
4天前
|
监控 Python
探索Python中的装饰器:从入门到实践
【10月更文挑战第31天】在Python的世界里,装饰器是那些隐藏在幕后的魔法师,它们拥有着改变函数行为的能力。本文将带你走进装饰器的世界,从基础概念到实际应用,一步步揭开它的神秘面纱。你将学会如何用几行代码增强你的函数功能,以及如何避免常见的陷阱。让我们一起来发现装饰器的魔力吧!
|
12天前
|
数据采集 机器学习/深度学习 人工智能
Python编程入门:从基础到实战
【10月更文挑战第24天】本文将带你进入Python的世界,从最基础的语法开始,逐步深入到实际的项目应用。我们将一起探索Python的强大功能和灵活性,无论你是编程新手还是有经验的开发者,都能在这篇文章中找到有价值的内容。让我们一起开启Python的奇妙之旅吧!
|
14天前
|
数据采集 存储 数据库
Python中实现简单爬虫的入门指南
【10月更文挑战第22天】本文将带你进入Python爬虫的世界,从基础概念到实战操作,一步步指导你如何使用Python编写一个简单的网络爬虫。我们将不展示代码示例,而是通过详细的步骤描述和逻辑讲解,帮助你理解爬虫的工作原理和开发过程。无论你是编程新手还是有一定经验的开发者,这篇文章都将为你打开一扇通往数据收集新世界的大门。
|
12天前
|
测试技术 开发者 Python
探索Python中的装饰器:从入门到实践
【10月更文挑战第24天】 在Python的世界里,装饰器是一个既神秘又强大的工具。它们就像是程序的“隐形斗篷”,能在不改变原有代码结构的情况下,增加新的功能。本篇文章将带你走进装饰器的世界,从基础概念出发,通过实际例子,逐步深入到装饰器的高级应用,让你的代码更加优雅和高效。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开一扇通往高效编程的大门。
|
14天前
|
存储 人工智能 数据挖掘
Python编程入门:构建你的第一个程序
【10月更文挑战第22天】编程,这个听起来高深莫测的词汇,实际上就像搭积木一样简单有趣。本文将带你走进Python的世界,用最浅显的语言和实例,让你轻松掌握编写第一个Python程序的方法。无论你是编程新手还是希望了解Python的爱好者,这篇文章都将是你的理想起点。让我们一起开始这段奇妙的编程之旅吧!
18 3
|
13天前
|
机器学习/深度学习 人工智能 算法
机器学习基础:使用Python和Scikit-learn入门
机器学习基础:使用Python和Scikit-learn入门
23 1
|
4天前
|
存储 机器学习/深度学习 搜索推荐
Python编程入门:从零开始构建你的第一个程序
【10月更文挑战第32天】本文旨在通过浅显易懂的方式引导编程新手进入Python的世界。我们将一起探索Python的基础语法,并通过实例学习如何构建一个简单的程序。文章将不直接展示代码,而是鼓励读者在阅读过程中自行尝试编写,以加深理解和记忆。无论你是编程初学者还是希望巩固基础知识的开发者,这篇文章都将是你的良师益友。让我们开始吧!
|
6天前
|
开发者 Python
探索Python中的装饰器:从入门到实战
【10月更文挑战第30天】本文将深入浅出地介绍Python中一个强大而有趣的特性——装饰器。我们将通过实际代码示例,一步步揭示装饰器如何简化代码、增强函数功能并保持代码的可读性。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开一扇通往更高效编程的大门。
下一篇
无影云桌面