How to use tail method in fMBT

Best Python code snippet using fMBT_python

_pvector.py

Source:_pvector.py Github

copy

Full Screen

...239 if (self._count >> SHIFT) > (1 << self._shift): # >>>240 new_root = [self._root, self._new_path(self._shift, self._tail)]241 new_shift += SHIFT242 else:243 new_root = self._push_tail(self._shift, self._root, self._tail)244 return new_root, new_shift245 def append(self, val):246 if len(self._tail) < BRANCH_FACTOR:247 new_tail = list(self._tail)248 new_tail.append(val)249 return PythonPVector(self._count + 1, self._shift, self._root, new_tail)250 # Full tail, push into tree251 new_root, new_shift = self._create_new_root()252 return PythonPVector(self._count + 1, new_shift, new_root, [val])253 def _new_path(self, level, node):254 if level == 0:255 return node256 return [self._new_path(level - SHIFT, node)]257 def _mutating_insert_tail(self):258 self._root, self._shift = self._create_new_root()259 self._tail = []260 def _mutating_fill_tail(self, offset, sequence):261 max_delta_len = BRANCH_FACTOR - len(self._tail)262 delta = sequence[offset:offset + max_delta_len]263 self._tail.extend(delta)264 delta_len = len(delta)265 self._count += delta_len266 return offset + delta_len267 def _mutating_extend(self, sequence):268 offset = 0269 sequence_len = len(sequence)270 while offset < sequence_len:271 offset = self._mutating_fill_tail(offset, sequence)272 if len(self._tail) == BRANCH_FACTOR:273 self._mutating_insert_tail()274 self._tail_offset = self._count - len(self._tail)275 def extend(self, obj):276 # Mutates the new vector directly for efficiency but that's only an277 # implementation detail, once it is returned it should be considered immutable278 l = obj.tolist() if isinstance(obj, PythonPVector) else list(obj)279 if l:280 new_vector = self.append(l[0])281 new_vector._mutating_extend(l[1:])282 return new_vector283 return self284 def _push_tail(self, level, parent, tail_node):285 """286 if parent is leaf, insert node,287 else does it map to an existing child? ->288 node_to_insert = push node one more level289 else alloc new path290 return node_to_insert placed in copy of parent291 """292 ret = list(parent)293 if level == SHIFT:294 ret.append(tail_node)295 return ret296 sub_index = ((self._count - 1) >> level) & BIT_MASK # >>>297 if len(parent) > sub_index:298 ret[sub_index] = self._push_tail(level - SHIFT, parent[sub_index], tail_node)299 return ret300 ret.append(self._new_path(level - SHIFT, tail_node))301 return ret302 def index(self, value, *args, **kwargs):303 return self.tolist().index(value, *args, **kwargs)304 def count(self, value):305 return self.tolist().count(value)306 def delete(self, index, stop=None):307 l = self.tolist()308 del l[_index_or_slice(index, stop)]309 return _EMPTY_PVECTOR.extend(l)310 def remove(self, value):311 l = self.tolist()312 l.remove(value)...

Full Screen

Full Screen

repeat.js

Source:repeat.js Github

copy

Full Screen

1/**2 * @license3 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.4 * This code may only be used under the BSD style license found at5 * http://polymer.github.io/LICENSE.txt6 * The complete set of authors may be found at7 * http://polymer.github.io/AUTHORS.txt8 * The complete set of contributors may be found at9 * http://polymer.github.io/CONTRIBUTORS.txt10 * Code distributed by Google as part of the polymer project is also11 * subject to an additional IP rights grant found at12 * http://polymer.github.io/PATENTS.txt13 */14import { createMarker, directive, NodePart, removeNodes, reparentNodes } from '../lit-html.js';15// Helper functions for manipulating parts16// TODO(kschaaf): Refactor into Part API?17const createAndInsertPart = (containerPart, beforePart) => {18 const container = containerPart.startNode.parentNode;19 const beforeNode = beforePart === undefined ? containerPart.endNode :20 beforePart.startNode;21 const startNode = container.insertBefore(createMarker(), beforeNode);22 container.insertBefore(createMarker(), beforeNode);23 const newPart = new NodePart(containerPart.options);24 newPart.insertAfterNode(startNode);25 return newPart;26};27const updatePart = (part, value) => {28 part.setValue(value);29 part.commit();30 return part;31};32const insertPartBefore = (containerPart, part, ref) => {33 const container = containerPart.startNode.parentNode;34 const beforeNode = ref ? ref.startNode : containerPart.endNode;35 const endNode = part.endNode.nextSibling;36 if (endNode !== beforeNode) {37 reparentNodes(container, part.startNode, endNode, beforeNode);38 }39};40const removePart = (part) => {41 removeNodes(part.startNode.parentNode, part.startNode, part.endNode.nextSibling);42};43// Helper for generating a map of array item to its index over a subset44// of an array (used to lazily generate `newKeyToIndexMap` and45// `oldKeyToIndexMap`)46const generateMap = (list, start, end) => {47 const map = new Map();48 for (let i = start; i <= end; i++) {49 map.set(list[i], i);50 }51 return map;52};53// Stores previous ordered list of parts and map of key to index54const partListCache = new WeakMap();55const keyListCache = new WeakMap();56/**57 * A directive that repeats a series of values (usually `TemplateResults`)58 * generated from an iterable, and updates those items efficiently when the59 * iterable changes based on user-provided `keys` associated with each item.60 *61 * Note that if a `keyFn` is provided, strict key-to-DOM mapping is maintained,62 * meaning previous DOM for a given key is moved into the new position if63 * needed, and DOM will never be reused with values for different keys (new DOM64 * will always be created for new keys). This is generally the most efficient65 * way to use `repeat` since it performs minimum unnecessary work for insertions66 * and removals.67 *68 * IMPORTANT: If providing a `keyFn`, keys *must* be unique for all items in a69 * given call to `repeat`. The behavior when two or more items have the same key70 * is undefined.71 *72 * If no `keyFn` is provided, this directive will perform similar to mapping73 * items to values, and DOM will be reused against potentially different items.74 */75export const repeat = directive((items, keyFnOrTemplate, template) => {76 let keyFn;77 if (template === undefined) {78 template = keyFnOrTemplate;79 }80 else if (keyFnOrTemplate !== undefined) {81 keyFn = keyFnOrTemplate;82 }83 return (containerPart) => {84 if (!(containerPart instanceof NodePart)) {85 throw new Error('repeat can only be used in text bindings');86 }87 // Old part & key lists are retrieved from the last update88 // (associated with the part for this instance of the directive)89 const oldParts = partListCache.get(containerPart) || [];90 const oldKeys = keyListCache.get(containerPart) || [];91 // New part list will be built up as we go (either reused from92 // old parts or created for new keys in this update). This is93 // saved in the above cache at the end of the update.94 const newParts = [];95 // New value list is eagerly generated from items along with a96 // parallel array indicating its key.97 const newValues = [];98 const newKeys = [];99 let index = 0;100 for (const item of items) {101 newKeys[index] = keyFn ? keyFn(item, index) : index;102 newValues[index] = template(item, index);103 index++;104 }105 // Maps from key to index for current and previous update; these106 // are generated lazily only when needed as a performance107 // optimization, since they are only required for multiple108 // non-contiguous changes in the list, which are less common.109 let newKeyToIndexMap;110 let oldKeyToIndexMap;111 // Head and tail pointers to old parts and new values112 let oldHead = 0;113 let oldTail = oldParts.length - 1;114 let newHead = 0;115 let newTail = newValues.length - 1;116 // Overview of O(n) reconciliation algorithm (general approach117 // based on ideas found in ivi, vue, snabbdom, etc.):118 //119 // * We start with the list of old parts and new values (and120 // arrays of their respective keys), head/tail pointers into121 // each, and we build up the new list of parts by updating122 // (and when needed, moving) old parts or creating new ones.123 // The initial scenario might look like this (for brevity of124 // the diagrams, the numbers in the array reflect keys125 // associated with the old parts or new values, although keys126 // and parts/values are actually stored in parallel arrays127 // indexed using the same head/tail pointers):128 //129 // oldHead v v oldTail130 // oldKeys: [0, 1, 2, 3, 4, 5, 6]131 // newParts: [ , , , , , , ]132 // newKeys: [0, 2, 1, 4, 3, 7, 6] <- reflects the user's new133 // item order134 // newHead ^ ^ newTail135 //136 // * Iterate old & new lists from both sides, updating,137 // swapping, or removing parts at the head/tail locations138 // until neither head nor tail can move.139 //140 // * Example below: keys at head pointers match, so update old141 // part 0 in-place (no need to move it) and record part 0 in142 // the `newParts` list. The last thing we do is advance the143 // `oldHead` and `newHead` pointers (will be reflected in the144 // next diagram).145 //146 // oldHead v v oldTail147 // oldKeys: [0, 1, 2, 3, 4, 5, 6]148 // newParts: [0, , , , , , ] <- heads matched: update 0149 // newKeys: [0, 2, 1, 4, 3, 7, 6] and advance both oldHead150 // & newHead151 // newHead ^ ^ newTail152 //153 // * Example below: head pointers don't match, but tail154 // pointers do, so update part 6 in place (no need to move155 // it), and record part 6 in the `newParts` list. Last,156 // advance the `oldTail` and `oldHead` pointers.157 //158 // oldHead v v oldTail159 // oldKeys: [0, 1, 2, 3, 4, 5, 6]160 // newParts: [0, , , , , , 6] <- tails matched: update 6161 // newKeys: [0, 2, 1, 4, 3, 7, 6] and advance both oldTail162 // & newTail163 // newHead ^ ^ newTail164 //165 // * If neither head nor tail match; next check if one of the166 // old head/tail items was removed. We first need to generate167 // the reverse map of new keys to index (`newKeyToIndexMap`),168 // which is done once lazily as a performance optimization,169 // since we only hit this case if multiple non-contiguous170 // changes were made. Note that for contiguous removal171 // anywhere in the list, the head and tails would advance172 // from either end and pass each other before we get to this173 // case and removals would be handled in the final while loop174 // without needing to generate the map.175 //176 // * Example below: The key at `oldTail` was removed (no longer177 // in the `newKeyToIndexMap`), so remove that part from the178 // DOM and advance just the `oldTail` pointer.179 //180 // oldHead v v oldTail181 // oldKeys: [0, 1, 2, 3, 4, 5, 6]182 // newParts: [0, , , , , , 6] <- 5 not in new map: remove183 // newKeys: [0, 2, 1, 4, 3, 7, 6] 5 and advance oldTail184 // newHead ^ ^ newTail185 //186 // * Once head and tail cannot move, any mismatches are due to187 // either new or moved items; if a new key is in the previous188 // "old key to old index" map, move the old part to the new189 // location, otherwise create and insert a new part. Note190 // that when moving an old part we null its position in the191 // oldParts array if it lies between the head and tail so we192 // know to skip it when the pointers get there.193 //194 // * Example below: neither head nor tail match, and neither195 // were removed; so find the `newHead` key in the196 // `oldKeyToIndexMap`, and move that old part's DOM into the197 // next head position (before `oldParts[oldHead]`). Last,198 // null the part in the `oldPart` array since it was199 // somewhere in the remaining oldParts still to be scanned200 // (between the head and tail pointers) so that we know to201 // skip that old part on future iterations.202 //203 // oldHead v v oldTail204 // oldKeys: [0, 1, -, 3, 4, 5, 6]205 // newParts: [0, 2, , , , , 6] <- stuck: update & move 2206 // newKeys: [0, 2, 1, 4, 3, 7, 6] into place and advance207 // newHead208 // newHead ^ ^ newTail209 //210 // * Note that for moves/insertions like the one above, a part211 // inserted at the head pointer is inserted before the212 // current `oldParts[oldHead]`, and a part inserted at the213 // tail pointer is inserted before `newParts[newTail+1]`. The214 // seeming asymmetry lies in the fact that new parts are215 // moved into place outside in, so to the right of the head216 // pointer are old parts, and to the right of the tail217 // pointer are new parts.218 //219 // * We always restart back from the top of the algorithm,220 // allowing matching and simple updates in place to221 // continue...222 //223 // * Example below: the head pointers once again match, so224 // simply update part 1 and record it in the `newParts`225 // array. Last, advance both head pointers.226 //227 // oldHead v v oldTail228 // oldKeys: [0, 1, -, 3, 4, 5, 6]229 // newParts: [0, 2, 1, , , , 6] <- heads matched: update 1230 // newKeys: [0, 2, 1, 4, 3, 7, 6] and advance both oldHead231 // & newHead232 // newHead ^ ^ newTail233 //234 // * As mentioned above, items that were moved as a result of235 // being stuck (the final else clause in the code below) are236 // marked with null, so we always advance old pointers over237 // these so we're comparing the next actual old value on238 // either end.239 //240 // * Example below: `oldHead` is null (already placed in241 // newParts), so advance `oldHead`.242 //243 // oldHead v v oldTail244 // oldKeys: [0, 1, -, 3, 4, 5, 6] <- old head already used:245 // newParts: [0, 2, 1, , , , 6] advance oldHead246 // newKeys: [0, 2, 1, 4, 3, 7, 6]247 // newHead ^ ^ newTail248 //249 // * Note it's not critical to mark old parts as null when they250 // are moved from head to tail or tail to head, since they251 // will be outside the pointer range and never visited again.252 //253 // * Example below: Here the old tail key matches the new head254 // key, so the part at the `oldTail` position and move its255 // DOM to the new head position (before `oldParts[oldHead]`).256 // Last, advance `oldTail` and `newHead` pointers.257 //258 // oldHead v v oldTail259 // oldKeys: [0, 1, -, 3, 4, 5, 6]260 // newParts: [0, 2, 1, 4, , , 6] <- old tail matches new261 // newKeys: [0, 2, 1, 4, 3, 7, 6] head: update & move 4,262 // advance oldTail & newHead263 // newHead ^ ^ newTail264 //265 // * Example below: Old and new head keys match, so update the266 // old head part in place, and advance the `oldHead` and267 // `newHead` pointers.268 //269 // oldHead v oldTail270 // oldKeys: [0, 1, -, 3, 4, 5, 6]271 // newParts: [0, 2, 1, 4, 3, ,6] <- heads match: update 3272 // newKeys: [0, 2, 1, 4, 3, 7, 6] and advance oldHead &273 // newHead274 // newHead ^ ^ newTail275 //276 // * Once the new or old pointers move past each other then all277 // we have left is additions (if old list exhausted) or278 // removals (if new list exhausted). Those are handled in the279 // final while loops at the end.280 //281 // * Example below: `oldHead` exceeded `oldTail`, so we're done282 // with the main loop. Create the remaining part and insert283 // it at the new head position, and the update is complete.284 //285 // (oldHead > oldTail)286 // oldKeys: [0, 1, -, 3, 4, 5, 6]287 // newParts: [0, 2, 1, 4, 3, 7 ,6] <- create and insert 7288 // newKeys: [0, 2, 1, 4, 3, 7, 6]289 // newHead ^ newTail290 //291 // * Note that the order of the if/else clauses is not292 // important to the algorithm, as long as the null checks293 // come first (to ensure we're always working on valid old294 // parts) and that the final else clause comes last (since295 // that's where the expensive moves occur). The order of296 // remaining clauses is is just a simple guess at which cases297 // will be most common.298 //299 // * TODO(kschaaf) Note, we could calculate the longest300 // increasing subsequence (LIS) of old items in new position,301 // and only move those not in the LIS set. However that costs302 // O(nlogn) time and adds a bit more code, and only helps303 // make rare types of mutations require fewer moves. The304 // above handles removes, adds, reversal, swaps, and single305 // moves of contiguous items in linear time, in the minimum306 // number of moves. As the number of multiple moves where LIS307 // might help approaches a random shuffle, the LIS308 // optimization becomes less helpful, so it seems not worth309 // the code at this point. Could reconsider if a compelling310 // case arises.311 while (oldHead <= oldTail && newHead <= newTail) {312 if (oldParts[oldHead] === null) {313 // `null` means old part at head has already been used314 // below; skip315 oldHead++;316 }317 else if (oldParts[oldTail] === null) {318 // `null` means old part at tail has already been used319 // below; skip320 oldTail--;321 }322 else if (oldKeys[oldHead] === newKeys[newHead]) {323 // Old head matches new head; update in place324 newParts[newHead] =325 updatePart(oldParts[oldHead], newValues[newHead]);326 oldHead++;327 newHead++;328 }329 else if (oldKeys[oldTail] === newKeys[newTail]) {330 // Old tail matches new tail; update in place331 newParts[newTail] =332 updatePart(oldParts[oldTail], newValues[newTail]);333 oldTail--;334 newTail--;335 }336 else if (oldKeys[oldHead] === newKeys[newTail]) {337 // Old head matches new tail; update and move to new tail338 newParts[newTail] =339 updatePart(oldParts[oldHead], newValues[newTail]);340 insertPartBefore(containerPart, oldParts[oldHead], newParts[newTail + 1]);341 oldHead++;342 newTail--;343 }344 else if (oldKeys[oldTail] === newKeys[newHead]) {345 // Old tail matches new head; update and move to new head346 newParts[newHead] =347 updatePart(oldParts[oldTail], newValues[newHead]);348 insertPartBefore(containerPart, oldParts[oldTail], oldParts[oldHead]);349 oldTail--;350 newHead++;351 }352 else {353 if (newKeyToIndexMap === undefined) {354 // Lazily generate key-to-index maps, used for removals &355 // moves below356 newKeyToIndexMap = generateMap(newKeys, newHead, newTail);357 oldKeyToIndexMap = generateMap(oldKeys, oldHead, oldTail);358 }359 if (!newKeyToIndexMap.has(oldKeys[oldHead])) {360 // Old head is no longer in new list; remove361 removePart(oldParts[oldHead]);362 oldHead++;363 }364 else if (!newKeyToIndexMap.has(oldKeys[oldTail])) {365 // Old tail is no longer in new list; remove366 removePart(oldParts[oldTail]);367 oldTail--;368 }369 else {370 // Any mismatches at this point are due to additions or371 // moves; see if we have an old part we can reuse and move372 // into place373 const oldIndex = oldKeyToIndexMap.get(newKeys[newHead]);374 const oldPart = oldIndex !== undefined ? oldParts[oldIndex] : null;375 if (oldPart === null) {376 // No old part for this value; create a new one and377 // insert it378 const newPart = createAndInsertPart(containerPart, oldParts[oldHead]);379 updatePart(newPart, newValues[newHead]);380 newParts[newHead] = newPart;381 }382 else {383 // Reuse old part384 newParts[newHead] =385 updatePart(oldPart, newValues[newHead]);386 insertPartBefore(containerPart, oldPart, oldParts[oldHead]);387 // This marks the old part as having been used, so that388 // it will be skipped in the first two checks above389 oldParts[oldIndex] = null;390 }391 newHead++;392 }393 }394 }395 // Add parts for any remaining new values396 while (newHead <= newTail) {397 // For all remaining additions, we insert before last new398 // tail, since old pointers are no longer valid399 const newPart = createAndInsertPart(containerPart, newParts[newTail + 1]);400 updatePart(newPart, newValues[newHead]);401 newParts[newHead++] = newPart;402 }403 // Remove any remaining unused old parts404 while (oldHead <= oldTail) {405 const oldPart = oldParts[oldHead++];406 if (oldPart !== null) {407 removePart(oldPart);408 }409 }410 // Save order of new parts for next round411 partListCache.set(containerPart, newParts);412 keyListCache.set(containerPart, newKeys);413 };...

Full Screen

Full Screen

Snake.js

Source:Snake.js Github

copy

Full Screen

1class Snake {2 constructor(x, y, size) {3 this.x = x;4 this.y = y;5 this.tail = [{ x: this.x, y: this.y }];6 this.size = size;7 this.rotateX = 0;8 this.rotateY = 1;9 }10 init() {}11 move() {12 if (this.rotateX == 1) {13 var newRect = {14 x: this.tail[this.tail.length - 1].x + 20,15 y: this.tail[this.tail.length - 1].y,16 };17 } else if (this.rotateX == -1) {18 var newRect = {19 x: this.tail[this.tail.length - 1].x - 20,20 y: this.tail[this.tail.length - 1].y,21 };22 } else if (this.rotateY == 1) {23 var newRect = {24 x: this.tail[this.tail.length - 1].x,25 y: this.tail[this.tail.length - 1].y + 20,26 };27 } else if (this.rotateY == -1) {28 var newRect = {29 x: this.tail[this.tail.length - 1].x,30 y: this.tail[this.tail.length - 1].y - 20,31 };32 }33 this.tail.shift();34 this.tail.push(newRect);35 }36}37class Apple {38 constructor() {39 var isTouching;40 while (true) {41 isTouching = false;42 this.x =43 Math.floor((Math.random() * canvas.width) / snake.size) * snake.size;44 this.y =45 Math.floor((Math.random() * canvas.height) / snake.size) * snake.size;46 for (var i = 0; i < snake.tail.length; i++) {47 if (this.x == snake.tail[i].x && this.y == snake.tail[i].y) {48 isTouching = true;49 }50 }51 if (!isTouching) {52 break;53 }54 }55 this.color = "pink";56 this.size = snake.size;57 }58}59var canvas = document.getElementById("canvas");60var snake = new Snake(20, 20, 20);61snake.init();62var apple = new Apple();63var canvasContext = canvas.getContext("2d");64window.onload = function () {65 gameLoop();66};67function gameLoop() {68 setInterval(show, 1000 / 15);69}70function show() {71 update();72 draw();73}74function update() {75 checkHit();76 keyCheck();77 canvasContext.clearRect(0, 0, canvas.width, canvas.heigth);78 eatApple();79 snake.move();80 checkHitWall();81}82function draw() {83 canvasContext.fillStyle = "black";84 createRect(0, 0, canvas.width, canvas.height);85 for (var i = 0; i < snake.tail.length; i++) {86 createRect(87 snake.tail[i].x + 2.5,88 snake.tail[i].y + 2.5,89 snake.size - 5,90 snake.size - 5,91 "white"92 );93 }94 canvasContext.font = "20px Arial";95 canvasContext.fillStyle = "#00FF42";96 canvasContext.fillText(97 "Score: " + (snake.tail.length - 1),98 canvas.width - 120,99 18100 );101 createRect(apple.x, apple.y, apple.size, apple.size, apple.color);102}103function createRect(x, y, width, height, color) {104 canvasContext.fillStyle = color;105 canvasContext.fillRect(x, y, width, height);106}107function createEmptyRect(x, y, width, height, color) {108 canvasContext.beginPath();109 canvasContext.lineWidth = "1";110 canvasContext.strokeStyle = color;111 canvasContext.rect(x, y, width, height);112 canvasContext.stroke();113}114function keyCheck() {115 window.addEventListener("keydown", (event) => {116 setTimeout(function () {117 if (event.keyCode == 37 && snake.rotateX != 1) {118 snake.rotateX = -1;119 snake.rotateY = 0;120 } else if (event.keyCode == 38 && snake.rotateY != 1) {121 snake.rotateX = 0;122 snake.rotateY = -1;123 } else if (event.keyCode == 39 && snake.rotateX != -1) {124 snake.rotateX = 1;125 snake.rotateY = 0;126 } else if (event.keyCode == 40 && snake.rotateY != -1) {127 snake.rotateX = 0;128 snake.rotateY = 1;129 }130 }, 1);131 });132}133function eatApple() {134 if (135 snake.tail[snake.tail.length - 1].x == apple.x &&136 snake.tail[snake.tail.length - 1].y == apple.y137 ) {138 snake.tail[snake.tail.length] = { x: apple.x, y: apple.y };139 apple = new Apple();140 }141}142function checkHit() {143 var isHit;144 for (var i = 0; i < snake.tail.length - 1; i++) {145 isHit = false;146 if (147 snake.tail[snake.tail.length - 1].x == snake.tail[i].x &&148 snake.tail[snake.tail.length - 1].y == snake.tail[i].y149 ) {150 isHit = true;151 }152 if (isHit) {153 console.log("yeap");154 snake = new Snake(20, 20, 20);155 }156 }157}158function checkHitWall() {159 var headTail = snake.tail[snake.tail.length - 1];160 if (headTail.x == -snake.size) {161 headTail.x = canvas.width - snake.size;162 }163 if (headTail.x == canvas.width) {164 headTail.x = 0;165 }166 if (headTail.y == -snake.size) {167 headTail.y = canvas.height - snake.size;168 }169 if (headTail.y == canvas.height) {170 headTail.y = 0;171 }...

Full Screen

Full Screen

queueWithCircularlyLinkedList.py

Source:queueWithCircularlyLinkedList.py Github

copy

Full Screen

...38 return value_to_return39 current_for_parse = current_for_parse.next_object40 count += 141 @property42 def tail(self):43 return self._tail44 @property45 def size(self):46 return self._size47 def first(self):48 if self.is_empty():49 raise Empty(self.MESSAGE_IF_EMPTY)50 element_to_return = self.tail.next_object51 return element_to_return.element52 def last(self):53 if self.is_empty():54 raise Empty(self.MESSAGE_IF_EMPTY)55 element_to_return = self.tail.element56 return element_to_return...

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run fMBT automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful