首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python类结构与继承

Python类结构与继承
EN

Stack Overflow用户
提问于 2018-09-20 18:07:37
回答 2查看 112关注 0票数 0

我对Python非常陌生,我正在努力解决类与继承等之间的关系。

假设我有一个类Student

代码语言:javascript
复制
class Student():
    def __init__(self, name):
        self.name = name

    def get_name(self):
        return self.name

    def set_name(self, name):
        self.name = name

这位学生可以参加多门课程:

代码语言:javascript
复制
class Course():
     def __init__(self, title):
         self.title = title

     def get_title(self):
         return self.title

     def set_title(self, title):
         self.title = title

每门课程也可以有多个学生。所以这是一种manyToMany关系。我的第一个想法是创建第三个类,名为StudentCourse

代码语言:javascript
复制
class StudentCourse(Student, Course):

     student_courses = {}

     def __init__(self, student, course):
         self.student = student
         self.course = course

     def add_student_to_course(self, student, course, results):
         self.student_courses[student] = {
             'course': course,
             'results': results
         }

     def get_student_courses(self, student):
         return self.student_courses.get(student)

这个结构正确吗?如果是这样,我的问题是:在学生类中,如何访问包含特定学生的课程和结果的student_courses字典?

编辑--我希望能够看到哪些学生参加了特定的课程,并获得了每个参加课程的学生的结果。

期待你的回复。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-20 19:00:17

这更像是一个基于观点的问题,而不是你能得到一个明确答案的问题。尽管如此,考虑到StudentCourse都是两个非常不同的实体,只有所有权才能连接到一起,因此没有必要在两者之间创建一个被屏蔽的类。

相反,我建议让他们两人以双链接的方式处理多到多关系中的一部分,即当你将Student添加到Course中时,你也会通知Student,他们现在是这门课程的一部分,反之亦然。类似于:

代码语言:javascript
复制
class Student(object):

    def __init__(self, name):
        self.name = name
        self.courses = {}  # we'll use a dict so that our courses can be mapped to results

    def add_course(self, course):
        if course not in self.courses:
            self.courses[course] = {}  # initialize each course with an empty dict
            # feel free to use any fields you like, like results etc.
            course.add_student(self)

    def del_course(self, course):
        self.courses.pop(course, None)
        course.del_student(self)

    def __repr__(self):  # just to ease our printouts
        return self.name

和:

代码语言:javascript
复制
class Course(object):

    def __init__(self, title):
        self.title = title
        self.students = set()  # a set ought to be enough

    def add_student(self, student):
        self.students.add(student)
        student.add_course(self)

    def del_student(self, student):
        self.students.discard(student)
        student.del_course(self)

    def __repr__(self):  # just to ease our printouts
        return self.title

然后你可以在两个方向上使用它们来建立你的多到多的关系,例如:

代码语言:javascript
复制
# Create some students and courses
john = Student("John Doe")
jane = Student("Jane Doe")
foo = Course("Foo Course")
bar = Course("Bar Course")

然后:

代码语言:javascript
复制
# initial state
print("John courses: {}".format(john.courses))  # John courses: {}
print("Jane courses: {}".format(jane.courses))  # Jane courses: {}
print("Foo students: {}".format(foo.students))  # Foo students: set([])
print("Bar students: {}".format(bar.students))  # Bar students: set([])

# lets add John to Foo:
john.add_course(foo)
print("John courses: {}".format(john.courses))  # John courses: {Foo Course: {}}
print("Foo students: {}".format(foo.students))  # Foo students: set([John Doe])

# lets add Jane to Bar, the other way around
bar.add_student(jane)
print("Jane courses: {}".format(jane.courses))  # Jane courses: {Bar Course: {}}
print("Bar students: {}".format(bar.students))  # Bar students: set([Jane Doe])

# lets add John to Bar as well
bar.add_student(john)
print("John courses: {}".format(john.courses))
# John courses: {Foo Course: {}, Bar Course: {}}
print("Bar students: {}".format(bar.students))
# Bar students: set([Jane Doe, John Doe])

# finally, lets add some info for the Foo course to John
john.courses[foo]["results"] = 94
print("John courses: {}".format(john.courses))
# John courses: {Foo Course: {'results': 94}, Bar Course: {}}

考虑到我们使用本机结构--集合和字典--来保存我们的关系,我们不仅可以自动防止重复条目,我们还可以很容易(非常快)检查关系,例如:

代码语言:javascript
复制
print("John is in Bar: {}".format(john in bar.students))  # John is in Bar: True
# or:
print("Bar is in John's courses: {}".format(bar in john.courses))
# Bar is in John's courses: True

print("Jane is in Foo: {}".format(jane in foo.students))  # Jane is in Foo: False

然后,您可以对其进行扩展,例如,将正在存储的结果和类似的结构正式化--您可以继续开发API以满足您的需要。祝好运!

票数 0
EN

Stack Overflow用户

发布于 2018-09-20 18:36:44

继承几乎肯定是表达Students和Courses之间关系的错误方式。继承表示IS-A关系。你的学生既不是课程,也不是你的课程学生。我也是-A错了。

你可能想要的是.每个Student都有--他们注册了许多Course。类似地,每个Course都注册了几个Student。在数据库中,您可以创建relationship对象来处理多到多的关系,但是在Python代码中,您可以使用数据结构。一份清单是自然的选择。下面的设计为每个学生添加了一个课程列表,并为每个课程添加了一个学生列表:

代码语言:javascript
复制
class Student:
    def __init__(self, name):
        self.name = name
        self.courses = []

    def enroll(self, course):
        self.courses.append(course)
        course.students.append(self)

class Course():
    def __init__(self, title):
        self.title = title
        self.students = []

    def enroll_student(self, student):
        student.enroll(self)

关于getter和setter的说明(与您的主要问题无关):您通常不需要用Python编写像get_nameset_name这样的方法。通常,如果这些方法没有执行任何操作(比如验证输入或以某种方式转换输出),则应该直接使用该属性。在其他语言中,编写和使用此类方法通常是最佳实践,即使您还不需要这些方法,但是在Python中,如果您后来决定需要进行一些验证,则可以使用property将属性查找的实现更改为方法调用。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52430876

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档