chore(i18n,learn): processed translations (#55187)

Co-authored-by: Naomi <commits@nhcarrigan.com>
This commit is contained in:
freeCodeCamp's Camper Bot
2024-06-13 18:37:33 -05:00
committed by GitHub
co-authored by Naomi
parent 8f14c7e9f8
commit ad20596e53
1368 changed files with 63453 additions and 5729 deletions
@@ -0,0 +1,32 @@
---
id: 65f01969115f933073b6be03
title: Step 1
challengeType: 20
dashedName: step-1
---
# --description--
A vector is an object that has a length (or magnitude) and a direction and it cannot be expressed by a single number. In physics, vectors are commonly used to represent forces, velocities, accelerations, and other quantities.
In this project you are going to build a vector space, a set in which a series of operations is defined between the elements in that set. You'll learn all the details very soon.
For now, start the project by declaring an empty class named `Vector`.
# --hints--
You should declare an empty class named `Vector`.
```js
({ test: () => assert(runPython(`_Node(_code).has_class("Vector")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
--fcc-editable-region--
```
@@ -0,0 +1,39 @@
---
id: 65f03d9f92eac9183a4d3281
title: Step 2
challengeType: 20
dashedName: step-2
---
# --description--
A vector can be defined by two coordinates, `x` and `y`, in the Euclidean plane. The distance between the origin of the axes and the point `(x, y)` will be its length, or norm. And the vector direction will point towards `(x, y)`.
<img class="img-responsive center-block" alt="a 2-dimensional vector of coordinates (2, 3)" src="https://cdn.freecodecamp.org/curriculum/python/2dvector.png" style="background-color: white; height: 350px; width: auto; padding: 15px;" />
Within the `Vector` class, create an `__init__` method and give it three parameters, `self`, `x`, and `y`.
# --hints--
You should define an `__init__` method inside the `Vector` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Vector").has_function("__init__")`)) })
```
Your `__init__` method should take three parameters: `self`, `x`, and `y`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Vector").find_function("__init__").has_args("self, x, y")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
class Vector:
pass
--fcc-editable-region--
```
@@ -0,0 +1,38 @@
---
id: 65f055b9190fc41ca35549b8
title: Step 3
challengeType: 20
dashedName: step-3
---
# --description--
Python offers various methods that include both a leading and trailing double underscore in their names. You may already be familiar with some, such as `__init__` and `__str__`. These methods, which follow the `__<name>__` naming pattern, are referred to as special methods, magic methods, or *dunder* (which stands for double underscore) methods.
Defining special methods in a class affects the behavior of that class. They are called under the hood in specific situations (e.g. `__init__` during instantiation, `__str__` when the object is printed or passed to `str()`). In this project, you are going to learn some of the most commonly used special methods.
For now, assign `x` to the `x` attribute of the `Vector` object.
# --hints--
You should assign `x` to `self.x`.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("Vector").find_function("__init__").has_stmt("self.x = x")
`))
})
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
class Vector:
def __init__(self, x, y):
pass
--fcc-editable-region--
```
@@ -0,0 +1,34 @@
---
id: 65f056a405239e1dc4cc2854
title: Step 4
challengeType: 20
dashedName: step-4
---
# --description--
Now, assign `y` to the `y` attribute of the `Vector` object.
# --hints--
You should assign `y` to `self.y`.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("Vector").find_function("__init__").find_variable("self.y").is_equivalent("self.y = y")
`))
})
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
class Vector:
def __init__(self, x, y):
self.x = x
--fcc-editable-region--
```
@@ -0,0 +1,45 @@
---
id: 65f058e06f34fd1f0ee6e55d
title: Step 5
challengeType: 20
dashedName: step-5
---
# --description--
Next, within the `Vector` class, create an empty `norm` method and give it a `self` parameter.
# --hints--
Your `Vector` class should have a `norm` method.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("Vector").has_function("norm")
`))
})
```
Your `norm` method should have a `self` parameter.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("Vector").find_function("norm").has_args("self")
`))
})
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
--fcc-editable-region--
```
@@ -0,0 +1,43 @@
---
id: 65f0694fb2296f3caadf8347
title: Step 6
challengeType: 20
dashedName: step-6
---
# --description--
The length of a vector $\mathbf{a}$, or norm, is typically indicated as $\\| \mathbf{a} \\|$. It can be calculated as the square root of the sum of its squared components: \\[ \\| \mathbf{a} \\| = \sqrt{a_1^2 + a_2^2 + \ldots + a_n^2} \\]
Compute the vector norm and return the result from your `norm` method.
# --hints--
Your `norm` method should use the provided formula to calculate and return a number representing the norm of the current vector instance. Do not approximate the value.
```js
({ test: () => runPython(`
v1 = Vector(2, 2.5)
v2 = Vector(0, -1)
v3 = Vector(-5, -0.3)
assert v1.norm() == 3.2015621187164243
assert v2.norm() == 1
assert v3.norm() == 5.008991914547277
`) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def norm(self):
pass
--fcc-editable-region--
```
@@ -0,0 +1,38 @@
---
id: 65f06a8e5a57673d700c79c3
title: Step 7
challengeType: 20
dashedName: step-7
---
# --description--
Outside the `Vector` class, create an instance of `Vector` passing the integers `2` and `3` as the `x` and `y` values and assign it to a variable named `v1`.
# --hints--
You should declare a variable `v1` and assign it `Vector(2, 3)`.
```js
({
test: () => assert(runPython(`
_Node(_code).find_variable("v1").is_equivalent("v1 = Vector(2, 3)")
`))
})
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def norm(self):
return (self.x**2 + self.y**2)**0.5
--fcc-editable-region--
```
@@ -0,0 +1,38 @@
---
id: 65f07c9b1ffb814d856dcffc
title: Step 8
challengeType: 20
dashedName: step-8
---
# --description--
Test that `norm` works as expected by printing the value returned by the method.
# --hints--
You should call `norm()` on `v1` and print the result.
```js
({
test: () => assert(runPython(`_Node(_code).has_call("print(v1.norm())")`))
})
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def norm(self):
return (self.x**2 + self.y**2)**0.5
v1 = Vector(2, 3)
--fcc-editable-region--
```
@@ -0,0 +1,55 @@
---
id: 65f3fa097f26b510db6c710b
title: Step 9
challengeType: 20
dashedName: step-9
---
# --description--
Great, `norm` is working as expected. Now, if you try to print `v1`, you'll get the default string representation of an object (something like `<__main__.Vector object at 0x11eb778>`).
Inside the `Vector` class, declare an empty `__str__` method to implement a readable string representation. Remember to give it a `self` parameter.
Pay attention to not print `v1` until `__str__` returns a string, otherwise you'll get a `TypeError`, because `__str__` must always return a string.
# --hints--
You should define a `__str__` method within the `Vector` class.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("Vector").has_function("__str__")
`))
})
```
Your `__str__` method should have a `self` parameter.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("Vector").find_function("__str__").has_args("self")
`))
})
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def norm(self):
return (self.x**2 + self.y**2)**0.5
v1 = Vector(2, 3)
print(v1.norm())
--fcc-editable-region--
```
@@ -0,0 +1,57 @@
---
id: 65f3fa60a93b84110b3f1708
title: Step 10
challengeType: 20
dashedName: step-10
---
# --description--
You want to return a meaningful string representation. For example, in the case of `v1`, you want to return a string containing the tuple with the values of the vector components: `(2, 3)`.
From the `__str__` method, return a string representing the vector as a tuple containing the vector components in order. Then, go outside the `Vector` class and print `v1` to check the result.
# --hints--
Your `__str__` method should return a string representing the vector as a tuple containing the vector components in order.
```js
({ test: () => runPython(`
v1 = Vector(2, 3)
v2 = Vector(0, 0)
v3 = Vector(-2, -3.5)
assert str(v1) == '(2, 3)'
assert str(v2) == '(0, 0)'
assert str(v3) == '(-2, -3.5)'
`) })
```
You should print `v1`.
```js
({
test: () => assert(runPython(`_Node(_code).has_call("print(v1)")`))
})
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def norm(self):
return (self.x**2 + self.y**2)**0.5
def __str__(self):
pass
v1 = Vector(2, 3)
print(v1.norm())
--fcc-editable-region--
```
@@ -0,0 +1,51 @@
---
id: 65f3fe07cc763212efe91285
title: Step 11
challengeType: 20
dashedName: step-11
---
# --description--
A vector can have a number `n` of dimensions (components). Here's a representation of a 3-dimensional vector:
<img class="img-responsive center-block" alt="a 3-dimensional vector of coordinates (4, 6, 3)" src="https://cdn.freecodecamp.org/curriculum/python/3dvector.png" style="background-color: white; height: 350px; width: auto; padding: 15px;" />
So far, you created a 2-dimensional vector. You want to be able to represent vectors with a different number of dimensions without rewriting the necessary code for each specific case. For that, you will use inheritance.
Start by renaming the `Vector` class into `R2Vector` to specify that this class is going to deal with 2-dimensional vectors. Remember to modify the instantiation of `v1`, too.
# --hints--
You should rename the `Vector` class into `R2Vector`. Remember to modify the instantiation of `v1`, too.
```js
({
test: () => assert(runPython(`
_Node(_code).has_class("R2Vector")
`))
})
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def norm(self):
return (self.x**2 + self.y**2)**0.5
def __str__(self):
return f'{self.x, self.y}'
v1 = Vector(2, 3)
print(v1.norm())
print(v1)
--fcc-editable-region--
```
@@ -0,0 +1,70 @@
---
id: 65f40051d6b09a139f253e8e
title: Step 12
challengeType: 20
dashedName: step-12
---
# --description--
Inheritance enables you to define a class from an existing one. The new class, called child, inherits all the methods and properties of the existing class, called parent.
```py
class Tree:
def sprout(self):
print('Making new leaves!')
class Oak(Tree):
pass
Oak().sprout() # Output: Making new leaves!
```
In the example above, the child class `Oak` inherits from `Tree` and inherits the `sprout` method from the parent class `Tree`.
Create a new class named `R3Vector` and follow the example above to make it inherit from the `R2Vector` class.
# --hints--
You should define a new class `R3Vector`.
```js
({
test: () => assert(runPython(`
_Node(_code).has_class("R3Vector")
`))
})
```
Your new class `R3Vector` should inherit from `R2Vector`.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R3Vector").inherits_from("R2Vector")
`))
})
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def norm(self):
return (self.x**2 + self.y**2)**0.5
def __str__(self):
return f'{self.x, self.y}'
--fcc-editable-region--
--fcc-editable-region--
v1 = R2Vector(2, 3)
print(v1.norm())
print(v1)
```
@@ -0,0 +1,56 @@
---
id: 65f40401e6ef53173c04e27d
title: Step 13
challengeType: 20
dashedName: step-13
---
# --description--
Within your new class, declare an `__init__` method. Give it `self`, `x`, `y`, and `z` as the parameters.
# --hints--
You should define an `__init__` method inside your `R3Vector` class.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R3Vector").has_function("__init__")
`))
})
```
Your `__init__` method should have four parameters `self`, `x`, `y`, and `z`.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, x, y, z")
`))
})
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def norm(self):
return (self.x**2 + self.y**2)**0.5
def __str__(self):
return f'{self.x, self.y}'
--fcc-editable-region--
class R3Vector(R2Vector):
pass
--fcc-editable-region--
v1 = R2Vector(2, 3)
print(v1.norm())
print(v1)
```
@@ -0,0 +1,49 @@
---
id: 65f407ea37ad6e181b90462e
title: Step 14
challengeType: 20
dashedName: step-14
---
# --description--
You could assign each `i` parameter to `self.i` as you did before. Although in this case you have few lines to repeat, one way to avoid this repetition is using the `super()` function. `super()` enables you to refer implicitly to the parent class: `super().__init__(x, y)` calls the `__init__` method of the parent class.
Add a `super().__init__(x, y)` call to your `__init__` method.
# --hints--
You should have a `super().__init__(x, y)` call in your `__init__` method.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R3Vector").find_function("__init__").has_stmt("super().__init__(x, y)")
`))
})
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def norm(self):
return (self.x**2 + self.y**2)**0.5
def __str__(self):
return f'{self.x, self.y}'
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, x, y, z):
pass
--fcc-editable-region--
v1 = R2Vector(2, 3)
print(v1.norm())
print(v1)
```
@@ -0,0 +1,47 @@
---
id: 65f40f8af784751c613d638a
title: Step 15
challengeType: 20
dashedName: step-15
---
# --description--
Now, you need to assign `z` to the `z` attribute of your `R3Vector` object.
# --hints--
You should assign `z` to `self.z` after the `super` call.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R3Vector").find_function("__init__").is_ordered("super().__init__(x, y)", "self.z = z")
`))
})
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def norm(self):
return (self.x**2 + self.y**2)**0.5
def __str__(self):
return f'{self.x, self.y}'
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, x, y, z):
super().__init__(x, y)
--fcc-editable-region--
v1 = R2Vector(2, 3)
print(v1.norm())
print(v1)
```
@@ -0,0 +1,47 @@
---
id: 65f40fdb3579aa1ced28b2eb
title: Step 16
challengeType: 20
dashedName: step-16
---
# --description--
Create an `R3Vector` instance with `2`, `2`, and `3` as the values of `x`, `y`, and `z`, respectively. Assign the new instance to `v2`.
# --hints--
You should declare a variable `v2` and assign it `R3Vector(2, 2, 3)`.
```js
({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(2, 2, 3)")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def norm(self):
return (self.x**2 + self.y**2)**0.5
def __str__(self):
return f'{self.x, self.y}'
class R3Vector(R2Vector):
def __init__(self, x, y, z):
super().__init__(x, y)
self.z = z
v1 = R2Vector(2, 3)
print(v1.norm())
print(v1)
--fcc-editable-region--
--fcc-editable-region--
```
@@ -0,0 +1,72 @@
---
id: 65f412c208c3791fee305acf
title: Step 17
challengeType: 20
dashedName: step-17
---
# --description--
In Python, you can enforce the use of keyword-only arguments by adding a `*` as an additional argument to the function or method signature. Modify both `__init__` methods by adding a `*` as the second parameter (after `self`). Every parameter placed after that will require the use of a keyword argument in the function/method call.
This means that you need to modify the `super().__init__(x, y)` call, too. Do it by giving `x` the value `x`, and `y` the value `y`.
Finally, modify the instantiation of `v1` and `v2` by using keyword arguments.
# --hints--
You should enforce keyword arguments by adding a `*` as the second parameter in both your `__init__` methods.
```js
({ test: () => {
assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__init__").has_args("self, *, x, y")`));
assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, *, x, y, z")`));
} })
```
You should modify your `super.__init__(x, y)` call to use keyword arguments.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").find_body().is_equivalent("super().__init__(x=x, y=y)\\nself.z = z")`)) })
```
You should modify the assignment of `v1` to be `R2Vector(x=2, y=3)`.
```js
({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R2Vector(x=2, y=3)")`)) })
```
You should modify the assignment of `v2` to be `R3Vector(x=2, y=2, z=3)`.
```js
({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=2, y=2, z=3)")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
class R2Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def norm(self):
return (self.x**2 + self.y**2)**0.5
def __str__(self):
return f'{self.x, self.y}'
class R3Vector(R2Vector):
def __init__(self, x, y, z):
super().__init__(x, y)
self.z = z
v1 = R2Vector(2, 3)
print(v1.norm())
print(v1)
v2 = R3Vector(2, 2, 3)
--fcc-editable-region--
```
@@ -0,0 +1,64 @@
---
id: 65f4148dea0f802040225e0c
title: Step 18
challengeType: 20
dashedName: step-18
---
# --description--
Remove the existing `print` calls. Then, as you did before for `v1`, print `v2` and the value returned by `v2.norm()`.
# --hints--
You should not have `print(v1)` and `print(v1.norm())` in your code.
```js
({
test: () => {
assert.isFalse(runPython(`_Node(_code).has_call("print(v1)")`));
assert.isFalse(runPython(`_Node(_code).has_call("print(v1.norm())")`));
}
})
```
You should print `v2` and `v2.norm()`.
```js
({
test: () => {
assert(runPython(`_Node(_code).has_call("print(v2)")`));
assert(runPython(`_Node(_code).has_call("print(v2.norm())")`));
}
})
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return (self.x**2 + self.y**2)**0.5
def __str__(self):
return f'{self.x, self.y}'
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
print(v1.norm())
print(v1)
v2 = R3Vector(x=2, y=2, z=3)
--fcc-editable-region--
```
@@ -0,0 +1,64 @@
---
id: 65f4520e363e2642f8112e33
title: Step 19
challengeType: 20
dashedName: step-19
---
# --description--
As you can see, something is not quite right. The `norm` and `__str__` methods inherited from `R2Vector` cannot adapt to a 3-dimensional vector. Their implementation has to be more flexible.
Every object in Python has a special attribute named `__dict__`, which is a dictionary that stores the object attributes.
Remove the existing `print` calls. Then, print the `__dict__` attribute of your `v1` and `v2` vectors to see what they look like.
# --hints--
You should not have `print(v2)` and `print(v2.norm())` in your code.
```js
({
test: () => {
assert.isFalse(runPython(`_Node(_code).has_call("print(v2)")`));
assert.isFalse(runPython(`_Node(_code).has_call("print(v2.norm())")`));
}
})
```
You should print the `__dict__` attribute of `v1` and `v2`.
```js
({ test: () => assert(runPython(`
(_Node(_code).has_call("print(v1.__dict__)") and _Node(_code).has_call("print(v2.__dict__)")) or _Node(_code).has_call("print(v1.__dict__, v2.__dict__)")
`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return (self.x**2 + self.y**2)**0.5
def __str__(self):
return f'{self.x, self.y}'
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(v2.norm())
print(v2)
--fcc-editable-region--
```
@@ -0,0 +1,49 @@
---
id: 65f4535bbdb28d436ff3ddc9
title: Step 20
challengeType: 20
dashedName: step-20
---
# --description--
As you can see from the output, `__dict__` contains the values of your instance attributes. Instead of explicitly adding the squares of `self.x` and `self.y`, you are going to iterate over the values stored in `__dict__` to calculate the value of the norm.
Within the `norm` method body, replace the content of the parentheses with a generator expression that elevates each value `val` in `self.__dict__.values()` to the power of `2`. Also, pass that generator expression as the argument to the `sum` function, so that all the squares are added together before calculating the square root.
# --hints--
You should return `sum(val**2 for val in self.__dict__.values())**0.5` from `norm()` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in self.__dict__.values())**0.5")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
--fcc-editable-region--
def norm(self):
return (self.x**2 + self.y**2)**0.5
--fcc-editable-region--
def __str__(self):
return f'{self.x, self.y}'
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(v1.__dict__)
print(v2.__dict__)
```
@@ -0,0 +1,53 @@
---
id: 65f870003444fb1a2ad171f2
title: Step 21
challengeType: 20
dashedName: step-21
---
# --description--
Modify the two `print` calls to print the norm of your vectors and verify that the `norm()` method works fine.
# --hints--
You should print `v1.norm()`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(v1.norm())")`)) })
```
You should print `v2.norm()`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(v2.norm())")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in self.__dict__.values())**0.5
def __str__(self):
return f'{self.x, self.y}'
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(v1.__dict__)
print(v2.__dict__)
--fcc-editable-region--
```
@@ -0,0 +1,61 @@
---
id: 65f8709620b2ce1a62608f5a
title: Step 23
challengeType: 20
dashedName: step-23
---
# --description--
When you need to dynamically access some attributes starting from a string input, the built-in `getattr()` function is what you need. It takes an object as its first argument, and a string containing the attribute name as its second attribute.
Start to fix the `__str__` method by replacing the string returned by `__str__()` with a generator expression that iterates through the object attributes and calls `getattr()` for each attribute `i`.
# --hints--
You should return a generator expression that iterates over `vars(self)`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_iters()[0].is_equivalent("vars(self)")`)) })
```
You should return a generator expression that uses `i` as the iteration variable.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_targets()[0].is_equivalent("i")`)) })
```
You should return a generator expression that calls `getattr(self, i)` for each item `i` in `vars(self)`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_expr().is_equivalent("getattr(self, i)")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
--fcc-editable-region--
def __str__(self):
return f'{self.x, self.y}'
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(v1.norm())
print(v2.norm())
```
@@ -0,0 +1,47 @@
---
id: 65f8720685ec351abef26740
title: Step 24
challengeType: 20
dashedName: step-24
---
# --description--
To obtain a proper string representation, call the `tuple()` constructor and pass it the generator expression you wrote in the previous step as the argument.
# --hints--
You should pass the expression returned by the `__str__` method to the `tuple()` constructor.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("tuple(getattr(self, i) for i in vars(self))")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
--fcc-editable-region--
def __str__(self):
return (getattr(self, i) for i in vars(self))
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(v1.norm())
print(v2.norm())
```
@@ -0,0 +1,47 @@
---
id: 65f872a0fe6aa21b456ad4fe
title: Step 25
challengeType: 20
dashedName: step-25
---
# --description--
Finally, pass the `tuple()` call as the argument to the `str()` function.
# --hints--
You should pass the `tuple()` call you are currently returning from the `__str__` method to the `str()` function.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("str(tuple(getattr(self, i) for i in vars(self)))")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
--fcc-editable-region--
def __str__(self):
return tuple(getattr(self, i) for i in vars(self))
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(v1.norm())
print(v2.norm())
```
@@ -0,0 +1,56 @@
---
id: 65f8749b13774b1d2e4a7fba
title: Step 27
challengeType: 20
dashedName: step-27
---
# --description--
While the `__str__` method returns a human-readable string representation of an object, the `__repr__` method is supposed to return the string needed to instantiate the object.
Add a `__repr__` method with a `self` parameter within the `R2Vector` class.
# --hints--
Your `R2Vector` class should have a `__repr__` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__repr__")`)) })
```
Your `__repr__` method should have a `self` parameter.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_args("self")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
--fcc-editable-region--
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
```
@@ -0,0 +1,74 @@
---
id: 65f876d17832001e8e1abb05
title: Step 28
challengeType: 20
dashedName: step-28
---
# --description--
Declare a variable `arg_list`. Give it the value of a list comprehension that iterates over `key` and `val` for each key-value pair in `vars(self).items()` and computes the f-string `f'{key}={val}'` at each iteration.
# --hints--
You should declare a variable `arg_list`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_variable("arg_list")`)) })
```
You should assign a list comprehension that iterates over `vars(self).items()` to `arg_list`.
```js
({ test: () => runPython(`
import ast
var = _Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list")
assert isinstance(var.tree.value, ast.ListComp), "Expected arg_list to be a list comprehension"
assert (actual := var.find_comp_iters()[0].is_equivalent("vars(self).items()")), f"Expected vars(self).items(), got {actual}"
`) })
```
The list comprehension assigned to `arg_list` should use `key` and `val` to iterate over `vars(self).items()`.
```js
({ test: () => assert(runPython(`
_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_targets()[0].is_equivalent("key, val")
`)) })
```
The list comprehension assigned to `arg_list` should compute the string `f'{key}={val}'` for each key-value pair in `vars(self).items()`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_expr().is_equivalent("f'{key}={val}'")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
--fcc-editable-region--
def __repr__(self):
pass
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
```
@@ -0,0 +1,50 @@
---
id: 65f93acbb514857003510e79
title: Step 29
challengeType: 20
dashedName: step-29
---
# --description--
Declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
# --hints--
You should declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("args").is_equivalent("args = ', '.join(arg_list)")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
--fcc-editable-region--
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
```
@@ -0,0 +1,52 @@
---
id: 65f93b67169a9c703264458a
title: Step 30
challengeType: 20
dashedName: step-30
---
# --description--
Since the method should return the string to instantiate the object for `R2Vector` as well as `R3Vector` when inherited, you cannot build the string specifying the class name.
You can access the name of a class with `__class__.__name__`. Add a `return` statement to the `__repr__` method and return the string necessary to instantiate the object.
# --hints--
You should use `__class__.__name__` to build the f-string needed to instantiate a vector object and return it from the `__repr__` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_return("f'{self.__class__.__name__}({args})'")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
--fcc-editable-region--
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
```
@@ -0,0 +1,57 @@
---
id: 65f93d4647ce2670dc6f095c
title: Step 31
challengeType: 20
dashedName: step-31
---
# --description--
The `__repr__` method is called under the hood by the `repr` function. Verify that `__repr__` works properly by adding `f'\nrepr = {repr(v1)}'` and `f'\nrepr = {repr(v2)}'` as the second argument to your first and second `print` calls, respectively.
# --hints--
You should add `f'\nrepr = {repr(v1)}'` as the second argument to your `print(f'v1 = {v1}')` call.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}', f'\\\\nrepr = {repr(v1)}')")`)) })
```
You should add `f'\nrepr = {repr(v2)}'` as the second argument to your `print(f'v2 = {v2}')` call.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}', f'\\\\nrepr = {repr(v2)}')")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
--fcc-editable-region--
```
@@ -0,0 +1,56 @@
---
id: 65f93e54a9121571dcdd3e79
title: Step 32
challengeType: 20
dashedName: step-32
---
# --description--
The output is correct, `repr` is giving you the string required to instantiate the objects.
Now comment out both your `print` calls.
# --hints--
You should comment out both your `print()` calls.
```js
({ test: () => {
assert.match(code, /#\s*print\s*\(\s*f('|")v1 = \{\s*v1\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v1\s*\)\s*\}\2\s*\)/);
assert.match(code, /#\s*print\s*\(\s*f('|")v2 = \{\s*v2\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v2\s*\)\s*\}\2\s*\)/);
} })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
--fcc-editable-region--
```
@@ -0,0 +1,62 @@
---
id: 65f9b17a638f0d0dcce8c354
title: Step 38
challengeType: 20
dashedName: step-38
---
# --description--
To create a vector space, you need to define how vectors should behave in several cases. Vectors can be added, forming a new vector.
The special method `__add__` can be implemented to override what happens by default when two objects are added together using the `+` operator.
Right now, trying to add two instances of `R2Vector` or `R3Vector` would raise an exception. Create an empty `__add__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
# --hints--
You should define an `__add__` method within the `R2Vector` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__add__")`)) })
```
Your `__add__` method should have two parameters, `self` and `other`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").has_args("self, other")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
--fcc-editable-region--
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
```
@@ -0,0 +1,58 @@
---
id: 65f9b486989cb90ff3e77ac8
title: Step 39
challengeType: 20
dashedName: step-39
---
# --description--
The `other` parameter of your `__add__` method represents the operand placed at the right side of the `+` operator in an addition operation.
You want to verify that the right-hand operand is not an object of the same class as the left-hand operand (i.e. `self`). Create an `if` statement that verifies that by checking the type of the operands.
# --hints--
You should create an `if` statement that checks if `type(self)` and `type(other)` are different.
```js
({ test: () => assert(runPython(`
node = _Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_conditions()[0]
node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
--fcc-editable-region--
def __add__(self, other):
pass
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
```
@@ -0,0 +1,58 @@
---
id: 65f9b9710cca621244d3bde1
title: Step 40
challengeType: 20
dashedName: step-40
---
# --description--
In Python, `NotImplemented` is a special value used to indicate that an operation is not implemented for a specific case.
`NotImplemented` does not raise an exception immediately. Instead, it signals to ask to the other operand how to perform the operation. If the request cannot be satisfied, a `TypeError` is returned by default.
Because you want to be able to sum two vectors only if they belong to the same class, return `NotImplemented` from the `if` statement you created in the previous step.
# --hints--
You should return `NotImplemented` from within the `if` body.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
--fcc-editable-region--
def __add__(self, other):
if type(self) != type(other):
pass
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
```
@@ -0,0 +1,58 @@
---
id: 65f9bb7c0d524612b2a88a4b
title: Step 41
challengeType: 20
dashedName: step-41
---
# --description--
After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
# --hints--
You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R2Vector").find_function("__add__").has_stmt("kwargs = {}")
`))
})
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
--fcc-editable-region--
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
```
@@ -0,0 +1,92 @@
---
id: 65f9bc10a9fb1612e066e9e8
title: Step 42
challengeType: 20
dashedName: step-42
---
# --description--
When adding two vectors, each component of one vector is added to the same component of the other vector. For example, adding `(1, 2)` and `(2, 4)` generates a third vector `(3, 6)`, where `3` is the sum of `1` and `2` and `6` is the sum of `2` and `4`.
The `kwargs` dictionary will contain the key-value pairs needed to instantiate a new vector of the same class of the two vectors added together.
Turn the empty dictionary into a dictionary comprehension that iterates through `vars(self)` and for each key (`i`) creates a key-value pair, where the key is the same key of the current iteration and its value is the sum of the values of the `i` attributes of the two operands.
# --hints--
You should turn the empty dictionary assigned to `kwargs` into a dictionary comprehension that iterates over `vars(self)`.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_iters()[0].is_equivalent("vars(self)")
`))
})
```
The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over `vars(self)`.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
`))
})
```
The dictionary comprehension assigned to `kwargs` should use `i` as the key.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_key().is_equivalent("i")
`))
})
```
The dictionary comprehension assigned to `kwargs` should assign the sum of the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i` in `vars(self)`. Use the `getattr()` function for that.
```js
({ test: () => assert(runPython(`
node = _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_expr()
node.is_equivalent("getattr(self, i) + getattr(other, i)") or node.is_equivalent("getattr(other, i) + getattr(self, i)")
`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
--fcc-editable-region--
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {}
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
```
@@ -0,0 +1,70 @@
---
id: 65f9c2c2006feb1428ad2d4c
title: Step 43
challengeType: 20
dashedName: step-43
---
# --description--
You can unpack a dictionary into keyword arguments by using the `**` operator:
```py
def spam(a, b):
return a + b
my_dict = {a: 11, b: 4}
spam(**my_dict) # 15
```
Return an instance of the current class by using `__class__` and passing `**kwargs` as the argument.
# --hints--
You should return `self.__class__(**kwargs)` from the `__add__` method.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R2Vector").find_function("__add__").has_return("self.__class__(**kwargs)")
`))
})
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
--fcc-editable-region--
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
```
@@ -0,0 +1,90 @@
---
id: 65f9cb678070ca1668898c70
title: Step 44
challengeType: 20
dashedName: step-44
---
# --description--
In the same way `__add__` is called under the hood when two objects are added together, the `__sub__` method is called implicitly in case of subtraction.
Now, define an empty `__sub__` method and give two parameters: `self`, and `other`. Inside your new method, create an if statement to check if `self` and `other` do not belong to the same class and return `NotImplemented`, as you did previously.
# --hints--
You should define a `__sub__` method within the `R2Vector` class.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R2Vector").has_function("__sub__")
`))
})
```
Your `__sub__` method should have two parameters, `self` and `other`.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R2Vector").find_function("__sub__").has_args("self, other")
`))
})
```
You should create an `if` statement that checks if `self` and `other` does not belong to the same class.
```js
({ test: () => assert(runPython(`
node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_conditions()[0]
node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
`))
})
```
You should return `NotImplemented` from within the `if` body.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
--fcc-editable-region--
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
```
@@ -0,0 +1,89 @@
---
id: 65f9dd6e5a08af19c196c2df
title: Step 45
challengeType: 20
dashedName: step-45
---
# --description--
The vector resulting from the subtraction of one vector from another is obtained by calculating the difference of each of their components. For example, subtracting `(2, 4)` from `(7, 3)` generates a third vector `(5, -1)`, where `5` is the difference between `7` and `2` and `-1` is the difference between `3` and `4`.
As you did before inside the `__add__` method, declare a `kwargs` variable after the `if` statement. Assign it a dictionary comprehension that iterates through the object attributes and creates a key-value pair for each key `i`, where the key is the same key as the current iteration and its value is the difference between the values of the `i` attributes of two operands.
# --hints--
You should declare a variable `kwargs` and assign it a dictionary comprehension that iterates over the object attributes.
```js
({ test: () => assert(runPython(`
node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_iters()[0]
node.is_equivalent("vars(self)") or node.is_equivalent("self.__dict__")`)) })
```
The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over the object attributes.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
`))
})
```
The dictionary comprehension assigned to `kwargs` should use `i` as the key.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_key().is_equivalent("i")`)) })
```
The dictionary comprehension assigned to `kwargs` should assign the difference between the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i`.
```js
({ test: () => assert(runPython(`
node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_expr()
node.is_equivalent("getattr(self, i) - getattr(other, i)") or node.is_equivalent("self.__getattribute__(i) - other.__getattribute__(i)")
`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
--fcc-editable-region--
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
```
@@ -0,0 +1,65 @@
---
id: 65f9dfd2e75e291a38695f13
title: Step 46
challengeType: 20
dashedName: step-46
---
# --description--
Finally, return a new vector object. Use `__class__` and unpack `kwargs` to instantiate the new vector.
# --hints--
You should return a new vector using `__class__` and unpacking `kwargs` from the `__sub__` method.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R2Vector").find_function("__sub__").has_return("self.__class__(**kwargs)")
`))
})
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
--fcc-editable-region--
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
```
@@ -0,0 +1,67 @@
---
id: 65f9e0a578b22c1a736f3d82
title: Step 47
challengeType: 20
dashedName: step-47
---
# --description--
Modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
# --hints--
You should modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
```js
({
test: () => assert(runPython(`
_Node(_code).has_stmt("v2 = R2Vector(x=0.5, y=1.25)")
`))
})
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
--fcc-editable-region--
```
@@ -0,0 +1,67 @@
---
id: 65fa8d5cf0ef3b141010f5d8
title: Step 48
challengeType: 20
dashedName: step-48
---
# --description--
It's time to verify that the addition and subtraction operations work as expected. Declare another variable `v3` and assign it the sum of `v1` plus `v2`.
# --hints--
You should declare a variable `v3` and assign it the sum of `v1` and `v2`.
```js
({
test: () => assert(runPython(`
_Node(_code).has_stmt("v3 = v1 + v2") or _Node(_code).has_stmt("v3 = v2 + v1")
`))
})
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
--fcc-editable-region--
```
@@ -0,0 +1,64 @@
---
id: 65fa8df56a0e2c149b4d24fe
title: Step 49
challengeType: 20
dashedName: step-49
---
# --description--
Next, check the new vector by printing the following f-string `f'v1 + v2 = {v3}'`.
# --hints--
You should print `f'v1 + v2 = {v3}'`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 + v2 = {v3}')")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
--fcc-editable-region--
```
@@ -0,0 +1,77 @@
---
id: 65fa9402d1fb5516aa42159d
title: Step 50
challengeType: 20
dashedName: step-50
---
# --description--
Feel free to modify `v3` so that it sums an `R2Vector` instance with an object of a different type, such as an integer or a string. You will be able to see a `TypeError` message printed on the console.
Then, restore the original line and create a new variable `v4`. Assign the difference between `v1` and `v2` to your new variable and print the result following the same structure as the previous f-string.
# --hints--
You should declare a variable `v4` and assign it the difference between `v1` and `v2`.
```js
({
test: () => assert(runPython(`
_Node(_code).has_stmt("v4 = v1 - v2")
`))
})
```
You should print `f'v1 - v2 = {v4}'`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 - v2 = {v4}')")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
--fcc-editable-region--
```
@@ -0,0 +1,85 @@
---
id: 65fa9e1b6c6db919385359ec
title: Step 51
challengeType: 20
dashedName: step-51
---
# --description--
The special method `__mul__` can be implemented to specify what should happen when the current instance is multiplied by another object.
Create an empty `__mul__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
# --hints--
You should define a `__mul__` method within the `R2Vector` class.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R2Vector").has_function("__mul__")
`))
})
```
Your `__mul__` method should have two parameters, `self` and `other`.
```js
({
test: () => assert(runPython(`
_Node(_code).find_class("R2Vector").find_function("__mul__").has_args("self, other")
`))
})
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
--fcc-editable-region--
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
```
@@ -0,0 +1,94 @@
---
id: 65faaed8f7a9772f023ea816
title: Step 52
challengeType: 20
dashedName: step-52
---
# --description--
Vectors can be multiplied by a *scalar*, i.e. a number that multiplies each single component. The result of scalar multiplication is a vector with the same orientation as the original vector but a different magnitude.
Implement the scalar multiplication by checking if `other` is either an `int` or a `float`. If it is, return a new instance of the current class that has each component of the starting vector multiplied by `other`. This will be the vector resulting from the scalar multiplication.
Make sure the methods can be applied to compute the scalar multiplication of vectors with any number of dimensions.
# --hints--
Your method should return a new instance of the current class only when the type of `other` is either `int` or `float`.
```js
({ test: () => runPython(`
v1 = R2Vector(x=0, y=0)
v2 = R3Vector(x=0, y=0, z=0)
types = ["", True, [], {}]
assert all((v1 * i) is None for i in types)
types = [1, 1.0]
assert all(type(v1 * i) is type(v1) for i in types)
assert all(type(v2 * i) is type(v2) for i in types)
`) })
```
The vector resulting from the scalar multiplication should have each component of the starting vector multiplied by the scalar.
```js
({ test: () => runPython(`
v1 = R2Vector(x=1, y=1.5)
v2 = R3Vector(x=2.2, y=3, z=-1)
assert vars(v1 * 3) == vars(R2Vector(x=3, y=4.5))
assert vars(v2 * (-2.0)) == vars(R3Vector(x=-4.4, y=-6.0, z=2.0))
`) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
--fcc-editable-region--
def __mul__(self, other):
pass
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
```
@@ -0,0 +1,79 @@
---
id: 65fc87e19930a503e5f05500
title: Step 53
challengeType: 20
dashedName: step-53
---
# --description--
A vector can be multiplied by another vector, too. This operation is called *dot product*, or *scalar product*.
Create an `elif` clause that checks if `other` is an object of the same class of the current instance.
You are going to implement the dot product inside this block during the next step.
# --hints--
You should create an `elif` clause that checks if `other` is an object of the same class of the current instance.
```js
({ test: () => assert(runPython(`
node = _Node(_code).find_class("R2Vector").find_function("__mul__").find_ifs()[0].find_conditions()[1]
node.is_equivalent("type(self) == type(other)") or node.is_equivalent("type(other) == type(self)")
`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
--fcc-editable-region--
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
```
@@ -0,0 +1,87 @@
---
id: 65fc899d77495504d6deeccc
title: Step 54
challengeType: 20
dashedName: step-54
---
# --description--
The scalar product between two vectors $\mathbf{a}$ and $\mathbf{b}$ is indicated as:
\\( \mathbf{a} \cdot \mathbf{b} = a_1 \cdot b_1 + a_2 \cdot b_2 + \ldots + a_n \cdot b_n = \sum_{i=1}^{n} a_i \cdot b_i \\)
Where each component of $\mathbf{a}$ is multiplied by the correspondent component of $\mathbf{b}$, and all the products are summed together, resulting in a number.
Within the `elif` clause, implement the above formula to compute the result of a scalar product and return the result. Remember that your implementation must be valid for any vector, independently from the number of components, when the method is inherited.
# --hints--
You should implement the scalar product calculation and return the result inside the `elif` body of your `__mul__` method.
```js
({ test: () => assert(runPython(`
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
v3 = R3Vector(x=2, y=3, z=1.5)
v4 = R3Vector(x=0.5, y=1.25, z=1.5)
v1*v2 == 4.75 and v3*v4 == 7.0
`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
--fcc-editable-region--
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
pass
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
```
@@ -0,0 +1,78 @@
---
id: 65fc8e7c766ab1070213aadb
title: Step 55
challengeType: 20
dashedName: step-55
---
# --description--
In case `other` is not an integer, a floating point number, or another instance of the current class, no product can be computed.
After the `elif` clause, return `NotImplemented`.
# --hints--
You should return `NotImplemented` after the `elif` clause.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__mul__").has_return("NotImplemented")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
--fcc-editable-region--
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
```
@@ -0,0 +1,82 @@
---
id: 65fc8fa7e7860407ab479bf0
title: Step 56
challengeType: 20
dashedName: step-56
---
# --description--
It's time to test the multiplication. Declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`. Then, call the `print` function and pass it the following f-string: `f'v1 * 3 = {v5}'`.
# --hints--
You should declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`.
```js
({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * 3")`)) })
```
You should print the f-string `f'v1 * 3 = {v5}'`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * 3 = {v5}')")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
--fcc-editable-region--
```
@@ -0,0 +1,87 @@
---
id: 65fd681b20b7e45f55def415
title: Step 57
challengeType: 20
dashedName: step-57
---
# --description--
The scalar multiplication works fine. Now, modify the assignment of `v5` to be the dot product `v1 * v2`. Also, update the `print` call.
Before doing that, feel free to experiment and multiply `v1` by an object of invalid type to see the error message printed on the console.
# --hints--
You should update the assignment of `v5` assigning it the scalar product `v1 * v2`.
```js
({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * v2")`)) })
```
You should update your `print` call to print the f-string `f'v1 * v2 = {v5}'`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * v2 = {v5}')")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * 3
print(f'v1 * 3 = {v5}')
--fcc-editable-region--
```
@@ -0,0 +1,87 @@
---
id: 65fd9250db0d6b8198cf29ef
title: Step 58
challengeType: 20
dashedName: step-58
---
# --description--
The `__eq__` method can be implemented to specify what should happen in case the comparison operator (`==`) is used to compare an object with something else.
Within the `R2Vector` class, create an `__eq__` method and give it two parameters: `self` and `other`.
# --hints--
You should define a `__eq__` method within the `R2Vector` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__eq__")`)) })
```
Your `__eq__` method should take two parameters: `self` and `other`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").has_args("self, other")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
--fcc-editable-region--
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
```
@@ -0,0 +1,88 @@
---
id: 65fd95c23beef982af29004c
title: Step 59
challengeType: 20
dashedName: step-59
---
# --description--
You want to compare two vectors, only when they belong to the same class. For that create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented` in that case.
# --hints--
You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
```js
({ test: () => assert(runPython(`
node = _Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_conditions()[0]
conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
any(node.is_equivalent(condition) for condition in conditions)`)) })
```
You should return `NotImplemented` from your `if` body.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
--fcc-editable-region--
def __eq__(self, other):
pass
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
```
@@ -0,0 +1,91 @@
---
id: 65fd97f3c1b4c4839bdeb8d2
title: Step 60
challengeType: 20
dashedName: step-60
---
# --description--
To compare two vectors, you are going to check that each component of the first vector is equal to the same component of the second vector.
After the `if` statement you created in the previous step, return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
# --hints--
The `__eq__` method should return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
```js
({ test: () => assert(runPython(`
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=2, y=3)
v3 = R2Vector(x=0.5, y=1.25)
v4 = R3Vector(x=2, y=3, z=1.5)
v5 = R3Vector(x=2, y=3, z=1.5)
v6 = R3Vector(x=0.5, y=1.25, z=1.5)
v1 == v2 and not v1 == v3 and v4 == v5 and not v5 == v6
`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
--fcc-editable-region--
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
```
@@ -0,0 +1,102 @@
---
id: 65fd9aa649f6cc84631882a9
title: Step 61
challengeType: 20
dashedName: step-61
---
# --description--
The `__ne__` method is called under the hood when the `!=` operator is used. Define a `__ne__` method with two parameters `self` and `other`. From your new method, return the opposite of `self == other`.
# --hints--
You should define a `__ne__` method within the `R2Vector` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ne__")`)) })
```
Your `__ne__` method should have two parameters, `self` and `other`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ne__").has_args("self, other")`)) })
```
The `__ne__` method should return `False` if each attribute of the current instance is equal to the same attribute of `other` and `True` otherwise.
```js
({ test: () => assert(runPython(`
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=2, y=3)
v3 = R2Vector(x=0.5, y=1.25)
v4 = R3Vector(x=2, y=3, z=1.5)
v5 = R3Vector(x=2, y=3, z=1.5)
v6 = R3Vector(x=0.5, y=1.25, z=1.5)
not v1 != v2 and v1 != v3 and not v4 != v5 and v5 != v6
`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
--fcc-editable-region--
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
```
@@ -0,0 +1,86 @@
---
id: 65fd9c6e49d7cd8513ab1005
title: Step 62
challengeType: 20
dashedName: step-62
---
# --description--
At the end of your code, use the equality operator to compare `v1` and `R2Vector(x=2, y=3)` and print the result.
# --hints--
You should print the result of comparing `v1` and `R2Vector(x=2, y=3)` using the equality operator.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 == R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) == v1)")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
--fcc-editable-region--
```
@@ -0,0 +1,87 @@
---
id: 65fd9d6203afea85931094c9
title: Step 63
challengeType: 20
dashedName: step-63
---
# --description--
The comparison returns `True`, since the two vectors have the same components. Now, modify the argument of the `print` call you added in the previous step to use the inequality operator.
# --hints--
You should modify the `print` call you added in the previous step using the inequality operator to compare `v1` and `R2Vector(x=2, y=3)`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) != v1)")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
print(v1 == R2Vector(x=2, y=3))
--fcc-editable-region--
```
@@ -0,0 +1,97 @@
---
id: 65fd9e2c56ff19862dfb8cbb
title: Step 64
challengeType: 20
dashedName: step-64
---
# --description--
The `__lt__` method is called under the hood when the `<` operator is used to compare an object with something else.
Add an empty `__lt__` method and give it two parameters: `self`, `other`.
# --hints--
You should define a `__lt__` method within the `R2Vector` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__lt__")`)) })
```
Your `__lt__` method should have two parameters, `self` and `other`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_args("self, other")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
--fcc-editable-region--
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
print(v1 != R2Vector(x=2, y=3))
```
@@ -0,0 +1,100 @@
---
id: 65fdc3c8478ee70fc7966151
title: Step 65
challengeType: 20
dashedName: step-65
---
# --description--
In the same way you did before for the `__eq__` method, create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
# --hints--
You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
```js
({ test: () => assert(runPython(`
node = _Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_conditions()[0]
conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
any(node.is_equivalent(condition) for condition in conditions)
`)) })
```
You should return `NotImplemented` from your `if` body.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
--fcc-editable-region--
def __lt__(self, other):
pass
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
print(v1 != R2Vector(x=2, y=3))
```
@@ -0,0 +1,91 @@
---
id: 65fdc496f4440e1055a2ac1b
title: Step 66
challengeType: 20
dashedName: step-66
---
# --description--
After the `if` statement, return the result of comparing the norm of the current instance with the norm of `other` using the less than operator.
# --hints--
The `__lt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the `<` operator.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_return("self.norm() < other.norm()")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
--fcc-editable-region--
def __lt__(self, other):
if type(self) != type(other):
return NotImplemented
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
print(v1 != R2Vector(x=2, y=3))
```
@@ -0,0 +1,122 @@
---
id: 6601918b44a11b4a8c986c6a
title: Step 67
challengeType: 20
dashedName: step-67
---
# --description--
The `__gt__` method is called under the hood when the `>` operator is used to compare an object with something else.
After the `__lt__` method, in the same way you did for `__lt__`, implement the `__gt__` method. Pay attention to use the appropriate operator.
# --hints--
You should define a `__gt__` method within the `R2Vector` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__gt__")`)) })
```
Your `__lt__` method should have two parameters, `self` and `other`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_args("self, other")`)) })
```
You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
```js
({ test: () => assert(runPython(`
node = _Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_conditions()[0]
node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")`)) })
```
You should return `NotImplemented` from your `if` body.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
```
The `__gt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the greater than operator.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_return("self.norm() > other.norm()")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
--fcc-editable-region--
def __lt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() < other.norm()
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
print(v1 != R2Vector(x=2, y=3))
```
@@ -0,0 +1,111 @@
---
id: 66019258a7c71d4ae50da42e
title: Step 68
challengeType: 20
dashedName: step-68
---
# --description--
There are still two possible comparisons to implement. The `__le__` method is called when the `<=` operator is used to compare two objects.
Define a `__le__` method with `self` and `other` as the parameters and make it return the opposite of `self > other`.
# --hints--
You should define a `__le__` method within the `R2Vector` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__le__")`)) })
```
Your `__le__` method should have two parameters, `self` and `other`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_args("self, other")`)) })
```
Your `__le__` method return the opposite of `self > other`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_return("not self > other")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
--fcc-editable-region--
def __lt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() < other.norm()
def __gt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() > other.norm()
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
print(v1 != R2Vector(x=2, y=3))
```
@@ -0,0 +1,116 @@
---
id: 66019319edb1cb4b57d3a793
title: Step 69
challengeType: 20
dashedName: step-69
---
# --description--
The last method you need is `__ge__`, which is called when the `>=` is used to compare two objects.
Define a `__ge__` method with `self` and `other` as the parameters and make it return the opposite of `self < other`.
# --hints--
You should define a `__ge__` method within the `R2Vector` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ge__")`)) })
```
Your `__ge__` method should have two parameters, `self` and `other`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_args("self, other")`)) })
```
Your `__ge__` method should return the opposite of `self < other`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_return("not self < other")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
def __lt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() < other.norm()
def __gt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() > other.norm()
def __le__(self, other):
return not self > other
--fcc-editable-region--
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
print(v1 != R2Vector(x=2, y=3))
```
@@ -0,0 +1,104 @@
---
id: 660193a2a71faa4bd8f10970
title: Step 70
challengeType: 20
dashedName: step-70
---
# --description--
Feel free to play around with the new comparison operations you implemented. Then, remove your last `print` call.
# --hints--
You should not have `print(v1 != R2Vector(x=2, y=3))` in your code.
```js
({test: () => assert.isFalse(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
def __lt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() < other.norm()
def __gt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() > other.norm()
def __le__(self, other):
return not self > other
def __ge__(self, other):
return not self < other
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
print(v1 != R2Vector(x=2, y=3))
--fcc-editable-region--
```
@@ -0,0 +1,111 @@
---
id: 66019977710caa516276c0a8
title: Step 71
challengeType: 20
dashedName: step-71
---
# --description--
The *cross product*, or *vector product*, is defined between 3-dimensional vectors and results in a third vector perpendicular to both of them.
The `R3Vector` class inherits from `R2Vector`, meaning it has access to all the methods and properties defined in `R2Vector`. A child class can implement additional features. You already saw a way to change the implementation of a method. Now, you are going to give the child class `R3Vector` a new method instead.
Within the `R3Vector` class, define a `cross` method and give it two parameters: `self`, and `other`.
# --hints--
You should define a `cross` method within the `R3Vector` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").has_function("cross")`)) })
```
Your `cross` method should have two parameters, `self` and `other`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").has_args("self, other")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
def __lt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() < other.norm()
def __gt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() > other.norm()
def __le__(self, other):
return not self > other
def __ge__(self, other):
return not self < other
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
```
@@ -0,0 +1,114 @@
---
id: 6601a7eb860fb8546516674d
title: Step 72
challengeType: 20
dashedName: step-72
---
# --description--
Create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
# --hints--
You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
```js
({ test: () => assert(runPython(`
node = _Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_conditions()[0]
conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
any(node.is_equivalent(condition) for condition in conditions)
`)) })
```
You should return `NotImplemented` from your `if` body.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
def __lt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() < other.norm()
def __gt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() > other.norm()
def __le__(self, other):
return not self > other
def __ge__(self, other):
return not self < other
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
def cross(self, other):
pass
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
```
@@ -0,0 +1,105 @@
---
id: 6601a88a6e2ccc550d7d7208
title: Step 73
challengeType: 20
dashedName: step-73
---
# --description--
After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
# --hints--
You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_variable("kwargs").is_equivalent("kwargs = {}")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
def __lt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() < other.norm()
def __gt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() > other.norm()
def __le__(self, other):
return not self > other
def __ge__(self, other):
return not self < other
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
def cross(self, other):
if type(self) != type(other):
return NotImplemented
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
```
@@ -0,0 +1,116 @@
---
id: 6601a8fb2e993b55912f9e9f
title: Step 74
challengeType: 20
dashedName: step-74
---
# --description--
The dot product between two 3D vectors \\( \mathbf{a} \\) and \\( \mathbf{b} \\) can be computed as it follows:
\\[ \mathbf{a} \times \mathbf{b} = \begin{pmatrix} a_yb_z - a_zb_y \\\ a_zb_x - a_xb_z \\\ a_xb_y - a_yb_x \end{pmatrix} \\]
Where the resulting vector is represented as a column vector.
Implement the formula above to compute the dot product between two 3-dimensional vectors and return the resulting vector from the `cross()` method.
# --hints--
The `cross()` method should return a new `R3Vector` instance resulting from the dot product computation.
```js
({ test: () => assert(runPython(`
v1 = R3Vector(x=2, y=3, z=1)
v2 = R3Vector(x=0.5, y=1.25, z=2)
v1.cross(v2) == R3Vector(x=4.75, y=-3.5, z=1.0) and v2.cross(v1) == R3Vector(x=-4.75, y=3.5, z=-1.0) and v1.cross(v1) == R3Vector(x=0, y=0, z=0)
`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
def __lt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() < other.norm()
def __gt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() > other.norm()
def __le__(self, other):
return not self > other
def __ge__(self, other):
return not self < other
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
def cross(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {}
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
```
@@ -0,0 +1,119 @@
---
id: 6601ab2809898f57591f2f7f
title: Step 75
challengeType: 20
dashedName: step-75
---
# --description--
Now, modify the assignments of `v1` and `v2`. Turn them into `R3Vector` instances and pass `z=1` and `z=2` to `v1` and `v2`, respectively.
# --hints--
You should modify the assignment of `v1` to be an `R3Vector` instance.
```js
({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R3Vector(x=2, y=3, z=1)")`)) })
```
You should modify the assignment of `v2` to be an `R3Vector` instance.
```js
({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=0.5, y=1.25, z=2)")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
def __lt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() < other.norm()
def __gt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() > other.norm()
def __le__(self, other):
return not self > other
def __ge__(self, other):
return not self < other
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
def cross(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {
'x': self.y * other.z - self.z * other.y,
'y': self.z * other.x - self.x * other.z,
'z': self.x * other.y - self.y * other.x
}
return self.__class__(**kwargs)
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R2Vector(x=0.5, y=1.25)
--fcc-editable-region--
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
```
@@ -0,0 +1,113 @@
---
id: 6601ac48a2ee6b59e6a5060d
title: Step 76
challengeType: 20
dashedName: step-76
---
# --description--
Call `cross()` on `v1` and pass `v2` as the argument. Assign this call to a new variable `v6`.
# --hints--
You should declare a variable named `v6` and assign it a call to the `cross()` method on `v1` passing it `v2` as the `argument`.
```js
({ test: () => assert(runPython(`_Node(_code).find_variable("v6").is_equivalent("v6 = v1.cross(v2)")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
def __lt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() < other.norm()
def __gt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() > other.norm()
def __le__(self, other):
return not self > other
def __ge__(self, other):
return not self < other
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
def cross(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {
'x': self.y * other.z - self.z * other.y,
'y': self.z * other.x - self.x * other.z,
'z': self.x * other.y - self.y * other.x
}
return self.__class__(**kwargs)
--fcc-editable-region--
v1 = R3Vector(x=2, y=3, z=1)
v2 = R3Vector(x=0.5, y=1.25, z=2)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
--fcc-editable-region--
```
@@ -0,0 +1,210 @@
---
id: 6601ad0fe415985a5c83f3cc
title: Step 77
challengeType: 20
dashedName: step-77
---
# --description--
As a final step, call the `print` function and pass it the f-string `f'v1 x v2 = {v6}'` to see the output of the dot product.
With that, you have completed the vector space project. Well done!
# --hints--
You should print `f'v1 x v2 = {v6}'`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 x v2 = {v6}')")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
def __lt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() < other.norm()
def __gt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() > other.norm()
def __le__(self, other):
return not self > other
def __ge__(self, other):
return not self < other
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
def cross(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {
'x': self.y * other.z - self.z * other.y,
'y': self.z * other.x - self.x * other.z,
'z': self.x * other.y - self.y * other.x
}
return self.__class__(**kwargs)
--fcc-editable-region--
v1 = R3Vector(x=2, y=3, z=1)
v2 = R3Vector(x=0.5, y=1.25, z=2)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
v6 = v1.cross(v2)
--fcc-editable-region--
```
# --solutions--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __add__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __sub__(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
return self.__class__(**kwargs)
def __mul__(self, other):
if type(other) in (int, float):
kwargs = {i: getattr(self, i) * other for i in vars(self)}
return self.__class__(**kwargs)
elif type(self) == type(other):
args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
return sum(args)
return NotImplemented
def __eq__(self, other):
if type(self) != type(other):
return NotImplemented
return all(getattr(self, i) == getattr(other, i) for i in vars(self))
def __ne__(self, other):
return not self == other
def __lt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() < other.norm()
def __gt__(self, other):
if type(self) != type(other):
return NotImplemented
return self.norm() > other.norm()
def __le__(self, other):
return not self > other
def __ge__(self, other):
return not self < other
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
def cross(self, other):
if type(self) != type(other):
return NotImplemented
kwargs = {
'x': self.y * other.z - self.z * other.y,
'y': self.z * other.x - self.x * other.z,
'z': self.x * other.y - self.y * other.x
}
return self.__class__(**kwargs)
v1 = R3Vector(x=2, y=3, z=1)
v2 = R3Vector(x=0.5, y=1.25, z=2)
print(f'v1 = {v1}')
print(f'v2 = {v2}')
v3 = v1 + v2
print(f'v1 + v2 = {v3}')
v4 = v1 - v2
print(f'v1 - v2 = {v4}')
v5 = v1 * v2
print(f'v1 * v2 = {v5}')
v6 = v1.cross(v2)
print(f'v1 x v2 = {v6}')
```
@@ -0,0 +1,53 @@
---
id: 6659875502b6d7765498f324
title: Step 26
challengeType: 20
dashedName: step-26
---
# --description--
Use f-strings to modify your `print` calls so that they result in the output `v1 = (2, 3)` and `v2 = (2, 2, 3)`, respectively.
# --hints--
You should use an f-string to interpolate `v1` and generate the output `v1 = (2, 3)`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}')")`)) })
```
You should use an f-string to interpolate `v2` and generate the output `v2 = (2, 2, 3)`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}')")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in self.__dict__.values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
--fcc-editable-region--
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(v1.norm())
print(v2.norm())
--fcc-editable-region--
```
@@ -0,0 +1,51 @@
---
id: 66680ddfd0f8c76782923cb0
title: Step 22
challengeType: 20
dashedName: step-22
---
# --description--
The `norm()` method is returning the correct values, but there's still something you can improve: readability.
The `vars()` built-in function takes an object as its argument and returns the `__dict__` attribute of that object.
Instead of directly accessing the `__dict__` attribute of `self`, modify the `norm` method to use the `vars()` function.
# --hints--
You should modify your `norm` method to use `vars(self)` instead of `self.__dict__`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in vars(self).values())**0.5")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
--fcc-editable-region--
def norm(self):
return sum(val**2 for val in self.__dict__.values())**0.5
--fcc-editable-region--
def __str__(self):
return f'{self.x, self.y}'
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
print(v1.norm())
print(v2.norm())
```
@@ -0,0 +1,61 @@
---
id: 66682150151af29efec9727d
title: Step 33
challengeType: 20
dashedName: step-33
---
# --description--
The `__getattribute__` method is called under the hood any time you try to access an instance attribute. If the attribute is not found at the instance level, the method will search for it at the class level, and eventually in parent classes.
Inside your class, define a `__getattribute__` method with two parameters, `self` and `attr`, and make it return the string `'calling __getattribute__'`. You'll override momentarily the default implementation just to see how the attribute access works.
# --hints--
You should define a method named `__getattribute__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_args("self, attr")`)) })
```
Your `__getattribute__` method should return the string `'calling __getattribute__'`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_return("'calling __getattribute__'")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
--fcc-editable-region--
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
```
@@ -0,0 +1,61 @@
---
id: 666826f258fda1ab3396a509
title: Step 34
challengeType: 20
dashedName: step-34
---
# --description--
Now, print the result of accessing the `x` attribute of `v1` both with the dot operator and the `getattr()` built-in function.
You will see that `__getattribute__` is called in both cases.
# --hints--
You should print the `x` attribute of `v1` using both the dot operator and the `getattr()` function.
```js
({ test: () => assert(runPython(`
n = _Node(_code)
(n.has_call("print(v1.x)") and n.has_call("print(getattr(v1, 'x'))")) or n.has_call("print(v1.x, getattr(v1, 'x'))") or n.has_call("print(getattr(v1, 'x'), v1.x)")
`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __getattribute__(self, attr):
return 'calling __getattribute__'
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
--fcc-editable-region--
--fcc-editable-region--
```
@@ -0,0 +1,69 @@
---
id: 666827a6fd0dbaafe8330ea6
title: Step 35
challengeType: 20
dashedName: step-35
---
# --description--
`__getattr__` is another special method that plays a role in accessing attributes.
The default implementation of `__getattribute__` is to raise an `AttributeError` when the requested attribute is not an instance attribute or it is not present in the class tree.
In that case, `__getattr__` is called if defined by the class. You can consider it as a sort of fallback when the usual attribute accessing procedure fails.
Turn the `__getattribute__` method into `__getattr__` and modify the string returned by the method into `'calling __getattr__'`.
# --hints--
You should define a method named `__getattr__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_args("self, attr")`)) })
```
Your `__getattr__` method should return the string `'calling __getattr__'`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_return("'calling __getattr__'")`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
--fcc-editable-region--
def __getattribute__(self, attr):
return 'calling __getattribute__'
--fcc-editable-region--
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
print(v1.x)
print(getattr(v1, 'x'))
```
@@ -0,0 +1,62 @@
---
id: 666832e427d70bc5219dc62a
title: Step 36
challengeType: 20
dashedName: step-36
---
# --description--
As you can see from the output, although you defined `__getattr__` in your class, this method is not called yet. This happens because the default attribute access occurs through `__getattribute__`. Therefore, you can see the attribute value printed on the terminal.
Now modify the last two lines of code to access the `z` attribute of `v1` in both your `print()` calls. This time, you are going to access an attribute that `v1` does not have. As a result, `__getattribute__` will raise an error and `__getattr__` will be called.
# --hints--
You should modify your code to print the `z` attribute of `v1` using both the dot operator and the `getattr()` function.
```js
({ test: () => assert(runPython(`
n = _Node(_code)
(n.has_call("print(v1.z)") and n.has_call("print(getattr(v1, 'z'))")) or n.has_call("print(v1.z, getattr(v1, 'z'))") or n.has_call("print(getattr(v1, 'z'), v1.z)")
`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
def __getattr__(self, attr):
return 'calling __getattr__'
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
--fcc-editable-region--
print(v1.x)
print(getattr(v1, 'x'))
--fcc-editable-region--
```
@@ -0,0 +1,75 @@
---
id: 6668374ed18b7fce10259cb3
title: Step 37
challengeType: 20
dashedName: step-37
---
# --description--
Now that you have an idea of how the attribute access work, remove the last two lines of your code together with the `__getattr__` method.
Then, restore the `print()` calls you commented out before and delete the second argument from both of them.
# --hints--
You should not have a `__getattr__` method.
```js
({ test: () => assert.isFalse(runPython(`_Node(_code).find_class("R2Vector").has_function("__getattr__")`)) })
```
You should not have `print(v1.z)`and `print(getattr(v1, 'z'))` in your code.
```js
({ test: () => assert.isFalse(runPython(`
n = _Node(_code)
n.has_call("print(v1.z)") or n.has_call("print(getattr(v1, 'z'))")
`)) })
```
You should restore the `print()` calls you commented out before and remove the second argument from both of them.
```js
({ test: () => assert(runPython(`
_Node(_code).has_call("print(f'v1 = {v1}')") and _Node(_code).has_call("print(f'v2 = {v2}')")
`)) })
```
# --seed--
## --seed-contents--
```py
class R2Vector:
def __init__(self, *, x, y):
self.x = x
self.y = y
def norm(self):
return sum(val**2 for val in vars(self).values())**0.5
def __str__(self):
return str(tuple(getattr(self, i) for i in vars(self)))
def __repr__(self):
arg_list = [f'{key}={val}' for key, val in vars(self).items()]
args = ', '.join(arg_list)
return f'{self.__class__.__name__}({args})'
--fcc-editable-region--
def __getattr__(self, attr):
return 'calling __getattr__'
class R3Vector(R2Vector):
def __init__(self, *, x, y, z):
super().__init__(x=x, y=y)
self.z = z
v1 = R2Vector(x=2, y=3)
v2 = R3Vector(x=2, y=2, z=3)
# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
print(v1.z)
print(getattr(v1, 'z'))
--fcc-editable-region--
```
@@ -1,6 +1,6 @@
---
id: 6553ed69ece88d29594748aa
title: Step 50
title: Step 52
challengeType: 20
dashedName: step-52
---
@@ -1,6 +1,6 @@
---
id: 6553efd6ada3f42aa2d75448
title: Step 51
title: Step 53
challengeType: 20
dashedName: step-53
---
@@ -1,6 +1,6 @@
---
id: 6553f3fc92741c2bf8ded140
title: Step 52
title: Step 54
challengeType: 20
dashedName: step-54
---
@@ -1,6 +1,6 @@
---
id: 6553f4f66099802c6ae94613
title: Step 53
title: Step 55
challengeType: 20
dashedName: step-55
---
@@ -1,6 +1,6 @@
---
id: 6553f6086add4b2cbb99fd78
title: Step 54
title: Step 56
challengeType: 20
dashedName: step-56
---
@@ -1,6 +1,6 @@
---
id: 6553f8c570f9982e013a8886
title: Step 55
title: Step 57
challengeType: 20
dashedName: step-57
---
@@ -1,6 +1,6 @@
---
id: 655491bd5b98b813fa5bedca
title: Step 56
title: Step 58
challengeType: 20
dashedName: step-58
---
@@ -1,6 +1,6 @@
---
id: 6554930320d70414e7b6acc6
title: Step 57
title: Step 59
challengeType: 20
dashedName: step-59
---
@@ -1,6 +1,6 @@
---
id: 65549561463f0016876e852c
title: Step 58
title: Step 60
challengeType: 20
dashedName: step-60
---
@@ -1,6 +1,6 @@
---
id: 65549f90cf78131c96ebcf28
title: Step 59
title: Step 61
challengeType: 20
dashedName: step-61
---
@@ -1,6 +1,6 @@
---
id: 6554a334a40edb1fb4eff827
title: Step 60
title: Step 62
challengeType: 20
dashedName: step-62
---
@@ -1,6 +1,6 @@
---
id: 6554a49a4f782f208abcc87e
title: Step 61
title: Step 63
challengeType: 20
dashedName: step-63
---
@@ -1,6 +1,6 @@
---
id: 6554a57ec0a2c52106e7ee50
title: Step 62
title: Step 64
challengeType: 20
dashedName: step-64
---
@@ -1,6 +1,6 @@
---
id: 6554a88d5af937226f4a9121
title: Step 63
title: Step 65
challengeType: 20
dashedName: step-65
---
@@ -1,6 +1,6 @@
---
id: 6554ac937a49be2701af4f2f
title: Step 64
title: Step 66
challengeType: 20
dashedName: step-66
---
@@ -1,6 +1,6 @@
---
id: 6554ad2463b8892748f8efdd
title: Step 65
title: Step 67
challengeType: 20
dashedName: step-67
---
@@ -1,6 +1,6 @@
---
id: 6554d0332949b133a0b35eaa
title: Step 66
title: Step 68
challengeType: 20
dashedName: step-68
---
@@ -1,6 +1,6 @@
---
id: 6554d15c8acb5f34499ad789
title: Step 67
title: Step 69
challengeType: 20
dashedName: step-69
---
@@ -1,6 +1,6 @@
---
id: 6554d25dc5ceaa354307a77e
title: Step 68
title: Step 70
challengeType: 20
dashedName: step-70
---
@@ -1,6 +1,6 @@
---
id: 6554de295ade563a069936a1
title: Step 69
title: Step 71
challengeType: 20
dashedName: step-71
---
@@ -1,6 +1,6 @@
---
id: 6554dfce1683be3c0c9609a6
title: Step 70
title: Step 72
challengeType: 20
dashedName: step-72
---
@@ -1,6 +1,6 @@
---
id: 6554e0adc7bb193cbfdb36d5
title: Step 71
title: Step 73
challengeType: 20
dashedName: step-73
---
@@ -1,6 +1,6 @@
---
id: 6554e2ee23bfd93f2c83640f
title: Step 72
title: Step 74
challengeType: 20
dashedName: step-74
---

Some files were not shown because too many files have changed in this diff Show More